bitkeeper revision 1.1034 (40e28d7bx0XoTn2USwCDCvPvUTLZjQ)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 30 Jun 2004 09:52:59 +0000 (09:52 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 30 Jun 2004 09:52:59 +0000 (09:52 +0000)
Rename ext to lowlevel.

23 files changed:
.rootkeys
tools/Make.defs
tools/python/setup.py
tools/python/xen/ext/__init__.py [deleted file]
tools/python/xen/ext/xc/Makefile [deleted file]
tools/python/xen/ext/xc/setup.py [deleted file]
tools/python/xen/ext/xc/xc.c [deleted file]
tools/python/xen/ext/xu/__init__.py [deleted file]
tools/python/xen/ext/xu/domain_controller.h [deleted file]
tools/python/xen/ext/xu/xu.c [deleted file]
tools/python/xen/lowlevel/__init__.py [new file with mode: 0644]
tools/python/xen/lowlevel/xc/xc.c [new file with mode: 0644]
tools/python/xen/lowlevel/xu/__init__.py [new file with mode: 0644]
tools/python/xen/lowlevel/xu/domain_controller.h [new file with mode: 0644]
tools/python/xen/lowlevel/xu/xu.c [new file with mode: 0644]
tools/python/xen/xend/XendConsole.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/XendNode.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/channel.py
tools/python/xen/xend/server/console.py
tools/python/xen/xend/server/messages.py

index 833c2f0cd227cb72b776d9846559a200002a03f4..5045bae458d9c08ddb95cfa14e802e8e4866dc9a 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
 40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/python/setup.py
 40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/python/xen/__init__.py
-40dfd40aMOhnw_cQLve9462UR5yYxQ tools/python/xen/ext/__init__.py
-3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/python/xen/ext/xc/Makefile
-3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/python/xen/ext/xc/setup.py
-3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/python/xen/ext/xc/xc.c
-40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/python/xen/ext/xu/__init__.py
-40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/ext/xu/domain_controller.h
-40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/ext/xu/xu.c
+40dfd40aMOhnw_cQLve9462UR5yYxQ tools/python/xen/lowlevel/__init__.py
+3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/python/xen/lowlevel/xc/xc.c
+40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/python/xen/lowlevel/xu/__init__.py
+40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/lowlevel/xu/domain_controller.h
+40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c
 40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
 40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
 4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/python/xen/util/console_client.py
index 051baef2fc6cbd8ad73bec456d5598672aa1d871..938b6cccb42ff95a02c6b0bf0f62fa24234cc9a6 100644 (file)
@@ -1,7 +1,7 @@
 #  -*- mode: Makefile; -*-
 XEN_HYPERVISOR_IFS = $(XEN_ROOT)/xen/include/hypervisor-ifs
 XEN_LINUX_INCLUDE  = $(XEN_ROOT)/linux-xen-sparse/include
-XEN_XU             = $(XEN_ROOT)/tools/python/xen/ext/xu
-XEN_XC             = $(XEN_ROOT)/tools/python/xen/ext/xc
+XEN_XU             = $(XEN_ROOT)/tools/python/xen/lowlevel/xu
+XEN_XC             = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_LIBXUTIL       = $(XEN_ROOT)/tools/libxutil
index 0b8efce0fd71a67a686c21469e48ba2dd37b46cf..93e7cad00cafc60a5e1cf13d24bbc644f378143c 100644 (file)
@@ -8,7 +8,7 @@ extra_compile_args  = [ "-fno-strict-aliasing", "-Wall", "-Werror" ]
 
 include_dirs = [ XEN_ROOT + "/xen/include/hypervisor-ifs",
                  XEN_ROOT + "/linux-xen-sparse/include",
-                 XEN_ROOT + "/tools/python/xen/ext/xu",
+                 XEN_ROOT + "/tools/python/xen/lowlevel/xu",
                  XEN_ROOT + "/tools/libxc",
                  XEN_ROOT + "/tools/libxutil",
                  ]
@@ -21,28 +21,28 @@ libraries = [ "xc", "xutil" ]
 
 xc = Extension("xc",
                extra_compile_args = extra_compile_args,
-               include_dirs       = include_dirs + [ "xen/ext/xc" ],
+               include_dirs       = include_dirs + [ "xen/lowlevel/xc" ],
                library_dirs       = library_dirs,
                libraries          = libraries,
-               sources            = [ "xen/ext/xc/xc.c" ])
+               sources            = [ "xen/lowlevel/xc/xc.c" ])
 
 xu = Extension("xu",
                extra_compile_args = extra_compile_args,
-               include_dirs       = include_dirs + [ "xen/ext/xu" ],
+               include_dirs       = include_dirs + [ "xen/lowlevel/xu" ],
                library_dirs       = library_dirs,
                libraries          = libraries,
-               sources            = [ "xen/ext/xu/xu.c" ])
+               sources            = [ "xen/lowlevel/xu/xu.c" ])
                
 setup(name            = 'xen',
       version         = '2.0',
       description     = 'Xen',
       packages        = ['xen',
-                         'xen.ext',
+                         'xen.lowlevel',
                          'xen.util',
                          'xen.xend',
                          'xen.xend.server',
                          'xen.xm',
                          ],
-      ext_package = "xen.ext",
+      ext_package = "xen.lowlevel",
       ext_modules = [ xc, xu ]
       )
diff --git a/tools/python/xen/ext/__init__.py b/tools/python/xen/ext/__init__.py
deleted file mode 100644 (file)
index 8d1c8b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
diff --git a/tools/python/xen/ext/xc/Makefile b/tools/python/xen/ext/xc/Makefile
deleted file mode 100644 (file)
index 7dc74a1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-
-clean:
-       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/python/xen/ext/xc/setup.py b/tools/python/xen/ext/xc/setup.py
deleted file mode 100644 (file)
index 8efe5ca..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-from distutils.core import setup, Extension
-
-module = Extension("xc",
-                   extra_compile_args   = ["-fno-strict-aliasing"],
-                   include_dirs         = ["../lib",
-                                           "../../../xen/include/hypervisor-ifs",
-                                           "../../../linux-xen-sparse/include",
-                                           "../../xu/lib",
-                                           "../../lib" ],
-                   library_dirs         = ["../lib",
-                                           "../../lib" ],
-                   libraries            = ["xc"],
-                   sources              = ["Xc.c"])
-
-setup(name = "xc",
-      version = "2.0",
-      ext_package = "xen.ext",
-      ext_modules = [module])
diff --git a/tools/python/xen/ext/xc/xc.c b/tools/python/xen/ext/xc/xc.c
deleted file mode 100644 (file)
index 003e1fa..0000000
+++ /dev/null
@@ -1,1184 +0,0 @@
-/******************************************************************************
- * Xc.c
- * 
- * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
- */
-
-#include <Python.h>
-#include <xc.h>
-#include <zlib.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include "xc_private.h"
-#include "gzip_stream.h"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-#define XENPKG "xen.ext.xc"
-
-static PyObject *xc_error, *zero;
-
-typedef struct {
-    PyObject_HEAD;
-    int xc_handle;
-} XcObject;
-
-/*
- * Definitions for the 'xc' object type.
- */
-
-static PyObject *pyxc_domain_create(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    unsigned int mem_kb = 0;
-    char        *name   = "(anon)";
-    int          cpu = -1;
-    u32          dom;
-    int          ret;
-
-    static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list, 
-                                      &mem_kb, &name, &cpu) )
-        return NULL;
-
-    if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return PyInt_FromLong(dom);
-}
-
-static PyObject *pyxc_domain_pause(PyObject *self,
-                                   PyObject *args,
-                                   PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-
-    if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_unpause(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-
-    if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_destroy(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-
-    if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_pincpu(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    int cpu = -1;
-
-    static char *kwd_list[] = { "dom", "cpu", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &dom, &cpu) )
-        return NULL;
-
-    if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_getinfo(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    PyObject *list;
-
-    u32 first_dom = 0;
-    int max_doms = 1024, nr_doms, i;
-    xc_dominfo_t *info;
-
-    static char *kwd_list[] = { "first_dom", "max_doms", NULL };
-    
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
-                                      &first_dom, &max_doms) )
-        return NULL;
-
-    if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
-        return PyErr_NoMemory();
-
-    nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
-    
-    list = PyList_New(nr_doms);
-    for ( i = 0 ; i < nr_doms; i++ )
-    {
-        PyList_SetItem(
-            list, i, 
-            Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
-                          ",s:l,s:L,s:s,s:l,s:i}",
-                          "dom",       info[i].domid,
-                          "cpu",       info[i].cpu,
-                          "dying",     info[i].dying,
-                          "crashed",   info[i].crashed,
-                          "shutdown",  info[i].shutdown,
-                          "paused",    info[i].paused,
-                          "blocked",   info[i].blocked,
-                          "running",   info[i].running,
-                          "mem_kb",    info[i].nr_pages*4,
-                          "cpu_time",  info[i].cpu_time,
-                          "name",      info[i].name,
-                          "maxmem_kb", info[i].max_memkb,
-                          "shutdown_reason", info[i].shutdown_reason
-                ));
-    }
-
-    free(info);
-
-    return list;
-}
-
-static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
-{
-    int rc = -1;
-    int fd = -1;
-    int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
-    int open_mode = 0644;
-
-    printf("%s>\n", __FUNCTION__);
-
-    if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
-    {
-        xcio_perror(ctxt, "Could not open file for writing");
-        goto exit;
-    }
-
-    printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
-
-    /* Compression rate 1: we want speed over compression. 
-     * We're mainly going for those zero pages, after all.
-     */
-    ctxt->io = gzip_stream_fdopen(fd, "wb1");
-    if ( ctxt->io == NULL )
-    {
-        xcio_perror(ctxt, "Could not allocate compression state");
-        goto exit;
-    }
-
-    printf("%s> xc_linux_save...\n", __FUNCTION__);
-
-    rc = xc_linux_save(xc->xc_handle, ctxt);
-
-  exit:
-    if ( ctxt->io != NULL )
-        IOStream_close(ctxt->io);
-    if ( fd >= 0 )
-        close(fd);
-    unlink(state_file);
-    printf("%s> rc=%d\n", __FUNCTION__, rc);
-    return rc;
-}
-
-static PyObject *pyxc_linux_save(PyObject *self,
-                                 PyObject *args,
-                                 PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    char *state_file;
-    int progress = 1, debug = 0;
-    PyObject *val = NULL;
-    int rc = -1;
-    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
-
-    static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 
-                                      &ioctxt.domain,
-                                      &state_file,
-                                      &ioctxt.vmconfig,
-                                      &progress, 
-                                      &debug) )
-        goto exit;
-
-    ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
-
-    if ( progress )
-        ioctxt.flags |= XCFLAGS_VERBOSE;
-    if ( debug )
-        ioctxt.flags |= XCFLAGS_DEBUG;
-
-    if ( (state_file == NULL) || (state_file[0] == '\0') )
-        goto exit;
-    
-    rc = file_save(xc, &ioctxt, state_file);
-    if ( rc != 0 )
-    {
-        PyErr_SetFromErrno(xc_error);
-        goto exit;
-    } 
-
-    Py_INCREF(zero);
-    val = zero;
-
-  exit:
-    return val;
-}
-
-
-static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
-{
-    int rc = -1;
-
-    ioctxt->io = gzip_stream_fopen(state_file, "rb");
-    if ( ioctxt->io == NULL )
-    {
-        xcio_perror(ioctxt, "Could not open file for reading");
-        return rc;
-    }
-
-    rc = xc_linux_restore(xc->xc_handle, ioctxt);
-
-    IOStream_close(ioctxt->io);
-    
-    return rc;
-}
-
-static PyObject *pyxc_linux_restore(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    char *state_file;
-    int progress = 1, debug = 0;
-    PyObject *val = NULL;
-    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
-    int rc =-1;
-
-    static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list,
-                                      &ioctxt.domain,
-                                      &state_file,
-                                      &progress,
-                                      &debug) )
-        goto exit;
-
-    if ( progress )
-        ioctxt.flags |= XCFLAGS_VERBOSE;
-    if ( debug )
-        ioctxt.flags |= XCFLAGS_DEBUG;
-
-    if ( (state_file == NULL) || (state_file[0] == '\0') )
-        goto exit;
-
-    rc = file_restore(xc, &ioctxt, state_file);
-    if ( rc != 0 )
-    {
-        PyErr_SetFromErrno(xc_error);
-        goto exit;
-    }
-
-    val = Py_BuildValue("{s:i,s:s}",
-                        "dom", ioctxt.domain,
-                        "vmconfig", ioctxt.vmconfig);
-
-  exit:
-    return val;
-}
-
-static PyObject *pyxc_linux_build(PyObject *self,
-                                  PyObject *args,
-                                  PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32   dom;
-    char *image, *ramdisk = NULL, *cmdline = "";
-    int   control_evtchn, flags = 0;
-
-    static char *kwd_list[] = { "dom", "control_evtchn", 
-                                "image", "ramdisk", "cmdline", "flags",
-                                NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
-                                      &dom, &control_evtchn, 
-                                      &image, &ramdisk, &cmdline, &flags) )
-        return NULL;
-
-    if ( xc_linux_build(xc->xc_handle, dom, image,
-                        ramdisk, cmdline, control_evtchn, flags) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_netbsd_build(PyObject *self,
-                                   PyObject *args,
-                                   PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32   dom;
-    char *image, *ramdisk = NULL, *cmdline = "";
-    int   control_evtchn;
-
-    static char *kwd_list[] = { "dom", "control_evtchn",
-                                "image", "ramdisk", "cmdline", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
-                                      &dom, &control_evtchn,
-                                      &image, &ramdisk, &cmdline) )
-        return NULL;
-
-    if ( xc_netbsd_build(xc->xc_handle, dom, image, 
-                         cmdline, control_evtchn) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_bvtsched_global_set(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    unsigned long ctx_allow;
-
-    static char *kwd_list[] = { "ctx_allow", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
-        return NULL;
-
-    if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_bvtsched_global_get(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    
-    unsigned long ctx_allow;
-    
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-    
-    if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
-}
-
-static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32           dom;
-    unsigned long mcuadv, warp, warpl, warpu;
-
-    static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
-                                "warpu", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
-                                      &dom, &mcuadv, &warp, &warpl, &warpu) )
-        return NULL;
-
-    if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, 
-                                warp, warpl, warpu) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 dom;
-    unsigned long mcuadv, warp, warpl, warpu;
-    
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-    
-    if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
-                                &warpl, &warpu) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
-                         "domain", dom,
-                         "mcuadv", mcuadv,
-                         "warp",   warp,
-                         "warpl",  warpl,
-                         "warpu",  warpu);
-}
-
-static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
-                                              PyObject *args,
-                                              PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
-    int port1, port2;
-
-    static char *kwd_list[] = { "dom1", "dom2", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, 
-                                      &dom1, &dom2) )
-        return NULL;
-
-    if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, 
-                                    dom2, &port1, &port2) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:i}", 
-                         "port1", port1,
-                         "port2", port2);
-}
-
-static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
-                                       PyObject *args,
-                                       PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    int virq, port;
-
-    static char *kwd_list[] = { "virq", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
-        return NULL;
-
-    if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return PyInt_FromLong(port);
-}
-
-static PyObject *pyxc_evtchn_close(PyObject *self,
-                                   PyObject *args,
-                                   PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom = DOMID_SELF;
-    int port;
-
-    static char *kwd_list[] = { "port", "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &port, &dom) )
-        return NULL;
-
-    if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_evtchn_send(PyObject *self,
-                                  PyObject *args,
-                                  PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    int port;
-
-    static char *kwd_list[] = { "port", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
-        return NULL;
-
-    if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_evtchn_status(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    PyObject *dict;
-
-    u32 dom = DOMID_SELF;
-    int port, ret;
-    xc_evtchn_status_t status;
-
-    static char *kwd_list[] = { "port", "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &port, &dom) )
-        return NULL;
-
-    ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
-    if ( ret != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    switch ( status.status )
-    {
-    case EVTCHNSTAT_closed:
-        dict = Py_BuildValue("{s:s}", 
-                             "status", "closed");
-        break;
-    case EVTCHNSTAT_unbound:
-        dict = Py_BuildValue("{s:s}", 
-                             "status", "unbound");
-        break;
-    case EVTCHNSTAT_interdomain:
-        dict = Py_BuildValue("{s:s,s:i,s:i}", 
-                             "status", "interdomain",
-                             "dom", status.u.interdomain.dom,
-                             "port", status.u.interdomain.port);
-        break;
-    case EVTCHNSTAT_pirq:
-        dict = Py_BuildValue("{s:s,s:i}", 
-                             "status", "pirq",
-                             "irq", status.u.pirq);
-        break;
-    case EVTCHNSTAT_virq:
-        dict = Py_BuildValue("{s:s,s:i}", 
-                             "status", "virq",
-                             "irq", status.u.virq);
-        break;
-    default:
-        dict = Py_BuildValue("{}");
-        break;
-    }
-    
-    return dict;
-}
-
-static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
-                                                PyObject *args,
-                                                PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 dom;
-    int bus, dev, func, enable, ret;
-
-    static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list, 
-                                      &dom, &bus, &dev, &func, &enable) )
-        return NULL;
-
-    ret = xc_physdev_pci_access_modify(
-        xc->xc_handle, dom, bus, dev, func, enable);
-    if ( ret != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_readconsolering(PyObject *self,
-                                      PyObject *args,
-                                      PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    unsigned int clear = 0;
-    char         str[32768];
-    int          ret;
-
-    static char *kwd_list[] = { "clear", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
-        return NULL;
-
-    ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
-    if ( ret < 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return PyString_FromStringAndSize(str, ret);
-}
-
-static PyObject *pyxc_physinfo(PyObject *self,
-                               PyObject *args,
-                               PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    xc_physinfo_t info;
-    
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xc_physinfo(xc->xc_handle, &info) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
-                         "ht_per_core", info.ht_per_core,
-                         "cores",       info.cores,
-                         "total_pages", info.total_pages,
-                         "free_pages",  info.free_pages,
-                         "cpu_khz",     info.cpu_khz);
-}
-
-static PyObject *pyxc_atropos_domain_set(PyObject *self,
-                                         PyObject *args,
-                                         PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 domid;
-    u64 period, slice, latency;
-    int xtratime;
-
-    static char *kwd_list[] = { "dom", "period", "slice", "latency",
-                                "xtratime", NULL };
-    
-    if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
-                                     &period, &slice, &latency, &xtratime) )
-        return NULL;
-   
-    if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
-                               latency, xtratime) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_atropos_domain_get(PyObject *self,
-                                         PyObject *args,
-                                         PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 domid;
-    u64 period, slice, latency;
-    int xtratime;
-    
-    static char *kwd_list[] = { "dom", NULL };
-
-    if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
-        return NULL;
-    
-    if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
-                                &slice, &latency, &xtratime ) )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
-                         "domain",  domid,
-                         "period",  period,
-                         "slice",   slice,
-                         "latency", latency,
-                         "xtratime", xtratime);
-}
-
-
-static PyObject *pyxc_rrobin_global_set(PyObject *self,
-                                        PyObject *args,
-                                        PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u64 slice;
-    
-    static char *kwd_list[] = { "slice", NULL };
-
-    if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
-        return NULL;
-    
-    if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_shadow_control(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    int op=0;
-
-    static char *kwd_list[] = { "dom", "op", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &dom, &op) )
-        return NULL;
-
-    if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_rrobin_global_get(PyObject *self,
-                                        PyObject *args,
-                                        PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u64 slice;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    return Py_BuildValue("{s:L}", "slice", slice);
-}
-
-static PyObject *pyxc_domain_setname(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 dom;
-    char *name;
-
-    static char *kwd_list[] = { "dom", "name", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list, 
-                                      &dom, &name) )
-        return NULL;
-
-    if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_setmaxmem(PyObject *self,
-                                       PyObject *args,
-                                       PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    unsigned long max_memkb;
-
-    static char *kwd_list[] = { "dom", "max_memkb", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
-                                      &dom, &max_memkb) )
-        return NULL;
-
-    if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-
-static PyMethodDef pyxc_methods[] = {
-    { "domain_create", 
-      (PyCFunction)pyxc_domain_create, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Create a new domain.\n"
-      " mem_kb [int, 0]:        Memory allocation, in kilobytes.\n"
-      " name   [str, '(anon)']: Informative textual name.\n\n"
-      "Returns: [int] new domain identifier; -1 on error.\n" },
-
-    { "domain_pause", 
-      (PyCFunction)pyxc_domain_pause, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Temporarily pause execution of a domain.\n"
-      " dom [int]: Identifier of domain to be paused.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_unpause", 
-      (PyCFunction)pyxc_domain_unpause, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "(Re)start execution of a domain.\n"
-      " dom [int]: Identifier of domain to be unpaused.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_destroy", 
-      (PyCFunction)pyxc_domain_destroy, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Destroy a domain.\n"
-      " dom [int]:    Identifier of domain to be destroyed.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_pincpu", 
-      (PyCFunction)pyxc_domain_pincpu, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Pin a domain to a specified CPU.\n"
-      " dom [int]:     Identifier of domain to be pinned.\n"
-      " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_getinfo", 
-      (PyCFunction)pyxc_domain_getinfo, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Get information regarding a set of domains, in increasing id order.\n"
-      " first_dom [int, 0]:    First domain to retrieve info about.\n"
-      " max_doms  [int, 1024]: Maximum number of domains to retrieve info"
-      " about.\n\n"
-      "Returns: [list of dicts] if list length is less than 'max_doms'\n"
-      "         parameter then there was an error, or the end of the\n"
-      "         domain-id space was reached.\n"
-      " dom      [int]: Identifier of domain to which this info pertains\n"
-      " cpu      [int]:  CPU to which this domain is bound\n"
-      " dying    [int]:  Bool - is the domain dying?\n"
-      " crashed  [int]:  Bool - has the domain crashed?\n"
-      " shutdown [int]:  Bool - has the domain shut itself down?\n"
-      " paused   [int]:  Bool - is the domain paused by control software?\n"
-      " blocked  [int]:  Bool - is the domain blocked waiting for an event?\n"
-      " running  [int]:  Bool - is the domain currently running?\n"
-      " mem_kb   [int]:  Memory reservation, in kilobytes\n"
-      " cpu_time [long]: CPU time consumed, in nanoseconds\n"
-      " name     [str]:  Identifying name\n"
-      " shutdown_reason [int]: Numeric code from guest OS, explaining "
-      "reason why it shut itself down.\n" },
-
-    { "linux_save", 
-      (PyCFunction)pyxc_linux_save, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Save the CPU and memory state of a Linux guest OS.\n"
-      " dom        [int]:    Identifier of domain to be saved.\n"
-      " state_file [str]:    Name of state file. Must not currently exist.\n"
-      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "linux_restore", 
-      (PyCFunction)pyxc_linux_restore, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Restore the CPU and memory state of a Linux guest OS.\n"
-      " state_file [str]:    Name of state file. Must not currently exist.\n"
-      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
-      "Returns: [int] new domain identifier on success; -1 on error.\n" },
-
-    { "linux_build", 
-      (PyCFunction)pyxc_linux_build, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Build a new Linux guest OS.\n"
-      " dom     [int]:      Identifier of domain to build into.\n"
-      " image   [str]:      Name of kernel image file. May be gzipped.\n"
-      " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
-      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "netbsd_build", 
-      (PyCFunction)pyxc_netbsd_build, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Build a new NetBSD guest OS.\n"
-      " dom     [int]:     Identifier of domain to build into.\n"
-      " image   [str]:      Name of kernel image file. May be gzipped.\n"
-      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "bvtsched_global_set",
-      (PyCFunction)pyxc_bvtsched_global_set,
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
-      " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "bvtsched_global_get",
-      (PyCFunction)pyxc_bvtsched_global_get,
-      METH_KEYWORDS, "\n"
-      "Get global tuning parameters for BVT scheduler.\n"
-      "Returns: [dict]:\n"
-      " ctx_allow [int]: context switch allowance\n" },
-
-    { "bvtsched_domain_set",
-      (PyCFunction)pyxc_bvtsched_domain_set,
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
-      " dom    [int]: Identifier of domain to be tuned.\n"
-      " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
-      " warp   [int]: How far to warp domain's EVT on unblock.\n"
-      " warpl  [int]: How long the domain can run warped.\n"
-      " warpu  [int]: How long before the domain can warp again.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "bvtsched_domain_get",
-      (PyCFunction)pyxc_bvtsched_domain_get,
-      METH_KEYWORDS, "\n"
-      "Get per-domain tuning parameters under the BVT scheduler.\n"
-      " dom [int]: Identifier of domain to be queried.\n"
-      "Returns [dict]:\n"
-      " domain [int]:  Domain ID.\n"
-      " mcuadv [long]: MCU Advance.\n"
-      " warp   [long]: Warp.\n"
-      " warpu  [long]: Unwarp requirement.\n"
-      " warpl  [long]: Warp limit,\n"
-    },
-
-    { "atropos_domain_set",
-      (PyCFunction)pyxc_atropos_domain_set,
-      METH_KEYWORDS, "\n"
-      "Set the scheduling parameters for a domain when running with Atropos.\n"
-      " dom      [int]:  domain to set\n"
-      " period   [long]: domain's scheduling period\n"
-      " slice    [long]: domain's slice per period\n"
-      " latency  [long]: wakeup latency hint\n"
-      " xtratime [int]: boolean\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "atropos_domain_get",
-      (PyCFunction)pyxc_atropos_domain_get,
-      METH_KEYWORDS, "\n"
-      "Get the current scheduling parameters for a domain when running with\n"
-      "the Atropos scheduler."
-      " dom      [int]: domain to query\n"
-      "Returns:  [dict]\n"
-      " domain   [int]: domain ID\n"
-      " period   [long]: scheduler period\n"
-      " slice    [long]: CPU reservation per period\n"
-      " latency  [long]: unblocking latency hint\n"
-      " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
-
-    { "rrobin_global_set",
-      (PyCFunction)pyxc_rrobin_global_set,
-      METH_KEYWORDS, "\n"
-      "Set Round Robin scheduler slice.\n"
-      " slice [long]: Round Robin scheduler slice\n"
-      "Returns: [int] 0 on success, throws an exception on failure\n" },
-
-    { "rrobin_global_get",
-      (PyCFunction)pyxc_rrobin_global_get,
-      METH_KEYWORDS, "\n"
-      "Get Round Robin scheduler settings\n"
-      "Returns [dict]:\n"
-      " slice  [long]: Scheduler time slice.\n" },    
-
-    { "evtchn_bind_interdomain", 
-      (PyCFunction)pyxc_evtchn_bind_interdomain, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Open an event channel between two domains.\n"
-      " dom1 [int, SELF]: First domain to be connected.\n"
-      " dom2 [int, SELF]: Second domain to be connected.\n\n"
-      "Returns: [dict] dictionary is empty on failure.\n"
-      " port1 [int]: Port-id for endpoint at dom1.\n"
-      " port2 [int]: Port-id for endpoint at dom2.\n" },
-
-    { "evtchn_bind_virq", 
-      (PyCFunction)pyxc_evtchn_bind_virq, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Bind an event channel to the specified VIRQ.\n"
-      " virq [int]: VIRQ to bind.\n\n"
-      "Returns: [int] Bound event-channel port.\n" },
-
-    { "evtchn_close", 
-      (PyCFunction)pyxc_evtchn_close, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Close an event channel.\n"
-      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
-      " port [int]:       Port-id of one endpoint of the channel.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "evtchn_send", 
-      (PyCFunction)pyxc_evtchn_send, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Send an event along a locally-connected event channel.\n"
-      " port [int]: Port-id of a local channel endpoint.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "evtchn_status", 
-      (PyCFunction)pyxc_evtchn_status, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Query the status of an event channel.\n"
-      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
-      " port [int]:       Port-id of one endpoint of the channel.\n\n"
-      "Returns: [dict] dictionary is empty on failure.\n"
-      " status [str]:  'closed', 'unbound', 'interdomain', 'pirq',"
-      " or 'virq'.\n"
-      "The following are returned if 'status' is 'interdomain':\n"
-      " dom  [int]: Dom-id of remote endpoint.\n"
-      " port [int]: Port-id of remote endpoint.\n"
-      "The following are returned if 'status' is 'pirq' or 'virq':\n"
-      " irq  [int]: IRQ number.\n" },
-
-    { "physdev_pci_access_modify",
-      (PyCFunction)pyxc_physdev_pci_access_modify,
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Allow a domain access to a PCI device\n"
-      " dom    [int]: Identifier of domain to be allowed access.\n"
-      " bus    [int]: PCI bus\n"
-      " dev    [int]: PCI slot\n"
-      " func   [int]: PCI function\n"
-      " enable [int]: Non-zero means enable access; else disable access\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-    { "readconsolering", 
-      (PyCFunction)pyxc_readconsolering, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Read Xen's console ring.\n"
-      " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
-      "Returns: [str] string is empty on failure.\n" },
-
-    { "physinfo",
-      (PyCFunction)pyxc_physinfo,
-      METH_VARARGS, "\n"
-      "Get information about the physical host machine\n"
-      "Returns [dict]: information about the hardware"
-      "        [None]: on failure.\n" },
-
-    { "shadow_control", 
-      (PyCFunction)pyxc_shadow_control, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set parameter for shadow pagetable interface\n"
-      " dom [int]:   Identifier of domain.\n"
-      " op [int, 0]: operation\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_setname", 
-      (PyCFunction)pyxc_domain_setname, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set domain informative textual name\n"
-      " dom [int]:  Identifier of domain.\n"
-      " name [str]: Text string.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_setmaxmem", 
-      (PyCFunction)pyxc_domain_setmaxmem, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set a domain's memory limit\n"
-      " dom [int]: Identifier of domain.\n"
-      " max_memkb [long]: .\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-
-/*
- * Definitions for the 'Xc' module wrapper.
- */
-
-staticforward PyTypeObject PyXcType;
-
-static PyObject *PyXc_new(PyObject *self, PyObject *args)
-{
-    XcObject *xc;
-
-    if ( !PyArg_ParseTuple(args, ":new") )
-        return NULL;
-
-    xc = PyObject_New(XcObject, &PyXcType);
-
-    if ( (xc->xc_handle = xc_interface_open()) == -1 )
-    {
-        PyObject_Del((PyObject *)xc);
-        return PyErr_SetFromErrno(xc_error);
-    }
-
-    return (PyObject *)xc;
-}
-
-static PyObject *PyXc_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(pyxc_methods, obj, name);
-}
-
-static void PyXc_dealloc(PyObject *self)
-{
-    XcObject *xc = (XcObject *)self;
-    (void)xc_interface_close(xc->xc_handle);
-    PyObject_Del(self);
-}
-
-static PyTypeObject PyXcType = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "Xc",
-    sizeof(XcObject),
-    0,
-    PyXc_dealloc,    /* tp_dealloc     */
-    NULL,            /* tp_print       */
-    PyXc_getattr,    /* tp_getattr     */
-    NULL,            /* tp_setattr     */
-    NULL,            /* tp_compare     */
-    NULL,            /* tp_repr        */
-    NULL,            /* tp_as_number   */
-    NULL,            /* tp_as_sequence */
-    NULL,            /* tp_as_mapping  */
-    NULL             /* tp_hash        */
-};
-
-static PyMethodDef PyXc_methods[] = {
-    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
-    { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxc(void)
-{
-    PyObject *m, *d;
-
-    m = Py_InitModule(XENPKG, PyXc_methods);
-
-    d = PyModule_GetDict(m);
-    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
-    PyDict_SetItemString(d, "error", xc_error);
-
-    zero = PyInt_FromLong(0);
-}
diff --git a/tools/python/xen/ext/xu/__init__.py b/tools/python/xen/ext/xu/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/python/xen/ext/xu/domain_controller.h b/tools/python/xen/ext/xu/domain_controller.h
deleted file mode 100644 (file)
index 76dd164..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/******************************************************************************
- * domain_controller.h
- * 
- * Interface to server controller (e.g., 'xend'). This header file defines the 
- * interface that is shared with guest OSes.
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __DOMAIN_CONTROLLER_H__
-#define __DOMAIN_CONTROLLER_H__
-
-
-#ifndef BASIC_START_INFO
-#error "Xen header file hypervisor-if.h must already be included here."
-#endif
-
-
-/*
- * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
- */
-
-typedef struct {
-    BASIC_START_INFO;
-    u16 domain_controller_evtchn; /* 320 */
-} PACKED extended_start_info_t; /* 322 bytes */
-#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
-#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
-
-
-/*
- * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
- * interpreted by control software to determine the appropriate action. These 
- * are only really advisories: the controller can actually do as it likes.
- */
-#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
-#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
-
-
-/*
- * CONTROLLER MESSAGING INTERFACE.
- */
-
-typedef struct {
-    u8 type;     /*  0: echoed in response */
-    u8 subtype;  /*  1: echoed in response */
-    u8 id;       /*  2: echoed in response */
-    u8 length;   /*  3: number of bytes in 'msg' */
-    u8 msg[60];  /*  4: type-specific message data */
-} PACKED control_msg_t; /* 64 bytes */
-
-#define CONTROL_RING_SIZE 8
-typedef u32 CONTROL_RING_IDX;
-#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
-
-typedef struct {
-    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
-    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
-    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
-    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
-} PACKED control_if_t; /* 1040 bytes */
-
-/*
- * Top-level command types.
- */
-#define CMSG_CONSOLE        0  /* Console                 */
-#define CMSG_BLKIF_BE       1  /* Block-device backend    */
-#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
-#define CMSG_NETIF_BE       3  /* Network-device backend  */
-#define CMSG_NETIF_FE       4  /* Network-device frontend */
-#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
-
-
-/******************************************************************************
- * CONSOLE DEFINITIONS
- */
-
-/*
- * Subtypes for console messages.
- */
-#define CMSG_CONSOLE_DATA       0
-
-
-/******************************************************************************
- * BLOCK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
-#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
-
-/* These are used by both front-end and back-end drivers. */
-#define blkif_vdev_t   u16
-#define blkif_pdev_t   u16
-#define blkif_sector_t u64
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its block interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32 handle; /*  0 */
-    u32 status; /*  4 */
-    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
-} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
-
-/*
- * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define BLKIF_DRIVER_STATUS_DOWN   0
-#define BLKIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32 nr_interfaces; /*  4 */
-} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32      handle;      /*  0 */
-    u32      __pad;
-    memory_t shmem_frame; /*  8 */
-    MEMORY_PADDING;
-} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32 handle; /*  0 */
-} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * BLOCK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
-#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
-#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
-#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
-#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
-#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
-
-/* Messages to domain controller. */
-#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for block-device messages.
- */
-
-typedef struct {
-    blkif_sector_t sector_start;   /*  0 */
-    blkif_sector_t sector_length;  /*  8 */
-    blkif_pdev_t   device;         /* 16 */
-    u16            __pad;          /* 18 */
-} PACKED blkif_extent_t; /* 20 bytes */
-
-/* Non-specific 'okay' return. */
-#define BLKIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define BLKIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
-#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define BLKIF_BE_STATUS_VBD_EXISTS          5
-#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
-#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
-#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
-#define BLKIF_BE_STATUS_MAPPING_ERROR       9
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define BLKIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "VBD already exists",           \
-    "VBD not found",                \
-    "Out of memory",                \
-    "Extent not found for VBD",     \
-    "Could not map domain memory" }
-
-/*
- * CMSG_BLKIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_create_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
-    MEMORY_PADDING;
-    u32        evtchn;        /* 16: Event channel for notifications.    */
-    /* OUT */
-    u32        status;        /* 20 */
-} PACKED blkif_be_connect_t;  /* 24 bytes */
-
-/*
- * CMSG_BLKIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_disconnect_t; /* 12 bytes */
-
-/* CMSG_BLKIF_BE_VBD_CREATE */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
-    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_create_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_DESTROY */
-typedef struct {
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_GROW */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
-    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 30 */
-    /* OUT */
-    u32        status;        /* 32 */
-} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
-
-/* CMSG_BLKIF_BE_VBD_SHRINK */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the controller
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
-#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
-
-/*
- * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its network interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32        handle; /*  0 */
-    u32        status; /*  4 */
-    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
-    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
-} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
-
-/*
- * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define NETIF_DRIVER_STATUS_DOWN   0
-#define NETIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32        nr_interfaces; /*  4 */
-} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32        handle;         /*  0 */
-    u32        __pad;          /*  4 */
-    memory_t   tx_shmem_frame; /*  8 */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16 */
-    MEMORY_PADDING;
-} PACKED netif_fe_interface_connect_t; /* 24 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32        handle;        /*  0 */
-} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
-#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
-#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-
-/* Messages to domain controller. */
-#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for net-device messages.
- */
-
-/* Non-specific 'okay' return. */
-#define NETIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define NETIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
-#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
-#define NETIF_BE_STATUS_MAPPING_ERROR       6
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define NETIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "Out of memory",                \
-    "Could not map domain memory" }
-
-/*
- * CMSG_NETIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    u8         mac[6];        /*  8 */
-    u16        __pad;         /* 14 */
-    /* OUT */
-    u32        status;        /* 16 */
-} PACKED netif_be_create_t; /* 20 bytes */
-
-/*
- * CMSG_NETIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u32        netif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32   status;             /*  8 */
-} PACKED netif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;          /*  0: Domain attached to new interface.   */
-    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
-    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
-    MEMORY_PADDING;
-    u16        evtchn;         /* 24: Event channel for notifications.    */
-    u16        __pad;          /* 26 */
-    /* OUT */
-    u32        status;         /* 28 */
-} PACKED netif_be_connect_t; /* 32 bytes */
-
-/*
- * CMSG_NETIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED netif_be_disconnect_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * SHUTDOWN DEFINITIONS
- */
-
-/*
- * Subtypes for shutdown messages.
- */
-#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
-#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
-#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
-                                    /* SHUTDOWN_suspend.                     */
-
-#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/python/xen/ext/xu/xu.c b/tools/python/xen/ext/xu/xu.c
deleted file mode 100644 (file)
index 48c9759..0000000
+++ /dev/null
@@ -1,1386 +0,0 @@
-/******************************************************************************
- * utils.c
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <Python.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xc.h>
-
-#include <hypervisor-if.h>
-#include "domain_controller.h"
-
-#include <asm-xen/proc_cmd.h>
-
-#define XENPKG "xen.ext.xu"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 200
-#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
-#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
-#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET  _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND   _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-/* Size of a machine page frame. */
-#define PAGE_SIZE 4096
-
-
-/*
- * *********************** NOTIFIER ***********************
- */
-
-typedef struct {
-    PyObject_HEAD;
-    int evtchn_fd;
-} xu_notifier_object;
-
-static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    u16 v;
-    int bytes;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-    
-    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
-    {
-        if ( errno == EINTR )
-            continue;
-        if ( errno == EAGAIN )
-            goto none;
-        return PyErr_SetFromErrno(PyExc_IOError);
-    }
-    
-    if ( bytes == sizeof(v) )
-        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
-
- none:
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    u16 v;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    v = (u16)idx;
-    
-    (void)write(xun->evtchn_fd, &v, sizeof(v));
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
-        return PyErr_SetFromErrno(PyExc_IOError);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
-        return PyErr_SetFromErrno(PyExc_IOError);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    return PyInt_FromLong(xun->evtchn_fd);
-}
-
-static PyMethodDef xu_notifier_methods[] = {
-    { "read",
-      (PyCFunction)xu_notifier_read,
-      METH_VARARGS,
-      "Read a (@port, @type) pair.\n" },
-
-    { "unmask", 
-      (PyCFunction)xu_notifier_unmask,
-      METH_VARARGS,
-      "Unmask notifications for a @port.\n" },
-
-    { "bind", 
-      (PyCFunction)xu_notifier_bind,
-      METH_VARARGS,
-      "Get notifications for a @port.\n" },
-
-    { "unbind", 
-      (PyCFunction)xu_notifier_unbind,
-      METH_VARARGS,
-      "No longer get notifications for a @port.\n" },
-
-    { "fileno", 
-      (PyCFunction)xu_notifier_fileno,
-      METH_VARARGS,
-      "Return the file descriptor for the notification channel.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_notifier_type;
-
-static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
-
- reopen:
-    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
-    if ( xun->evtchn_fd == -1 )
-    {
-        if ( (errno == ENOENT) &&
-             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
-             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
-                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
-            goto reopen;
-        PyObject_Del((PyObject *)xun);
-        return PyErr_SetFromErrno(PyExc_IOError);
-    }
-
-    return (PyObject *)xun;
-}
-
-static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
-{
-    if ( strcmp(name, "EXCEPTION") == 0 )
-        return PyInt_FromLong(PORT_EXCEPTION);
-    if ( strcmp(name, "NORMAL") == 0 )
-        return PyInt_FromLong(PORT_NORMAL);
-    return Py_FindMethod(xu_notifier_methods, obj, name);
-}
-
-static void xu_notifier_dealloc(PyObject *self)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    (void)close(xun->evtchn_fd);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_notifier_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "notifier",
-    sizeof(xu_notifier_object),
-    0,
-    xu_notifier_dealloc, /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_notifier_getattr, /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MESSAGE ***********************
- */
-
-#define TYPE(_x,_y) (((_x)<<8)|(_y))
-#define P2C(_struct, _field, _ctype)                                      \
-    do {                                                                  \
-        PyObject *obj;                                                    \
-        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
-        {                                                                 \
-            if ( PyInt_Check(obj) )                                       \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyInt_AsLong(obj);                              \
-                dict_items_parsed++;                                      \
-            }                                                             \
-            else if ( PyLong_Check(obj) )                                 \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
-                dict_items_parsed++;                                      \
-            }                                                             \
-        }                                                                 \
-        xum->msg.length = sizeof(_struct);                                \
-    } while ( 0 )
-#define C2P(_struct, _field, _pytype, _ctype)                             \
-    do {                                                                  \
-        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
-                        (((_struct *)&xum->msg.msg[0])->_field);          \
-        if ( dict == NULL ) dict = PyDict_New();                          \
-        PyDict_SetItemString(dict, #_field, obj);                         \
-    } while ( 0 )
-
-typedef struct {
-    PyObject_HEAD;
-    control_msg_t msg;
-} xu_message_object;
-
-static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    char *str;
-    int len;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
-    {
-        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
-        return NULL;
-    }
-
-    memcpy(&xum->msg.msg[xum->msg.length], str, len);
-    xum->msg.length += len;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *payload;
-    int dict_items_parsed = 0;
-
-    if ( !PyArg_ParseTuple(args, "O", &payload) )
-        return NULL;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        return NULL;
-    }
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *dict = NULL;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
-        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
-        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
-        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        C2P(blkif_be_create_t, domid,        Int, Long);
-        C2P(blkif_be_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        C2P(blkif_be_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        C2P(blkif_be_connect_t, domid,        Int, Long);
-        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
-        C2P(blkif_be_connect_t, evtchn,       Int, Long);
-        C2P(blkif_be_connect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        C2P(blkif_be_disconnect_t, domid,        Int, Long);
-        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
-        C2P(blkif_be_vbd_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
-        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
-        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
-        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
-        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
-             Long, UnsignedLongLong);
-        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
-             Long, UnsignedLongLong);
-        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
-        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
-        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
-        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
-        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
-        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
-        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        C2P(netif_be_create_t, domid,        Int, Long);
-        C2P(netif_be_create_t, netif_handle, Int, Long);
-        C2P(netif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        C2P(netif_be_destroy_t, domid,        Int, Long);
-        C2P(netif_be_destroy_t, netif_handle, Int, Long);
-        C2P(netif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        C2P(netif_be_connect_t, domid,          Int, Long);
-        C2P(netif_be_connect_t, netif_handle,   Int, Long);
-        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, evtchn,         Int, Long);
-        C2P(netif_be_connect_t, status,         Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        C2P(netif_be_disconnect_t, domid,        Int, Long);
-        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
-        C2P(netif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(netif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    }
-
-    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
-}
-
-static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    return Py_BuildValue("{s:i,s:i,s:i}",
-                         "type",    xum->msg.type,
-                         "subtype", xum->msg.subtype,
-                         "id",      xum->msg.id);
-}
-
-static PyMethodDef xu_message_methods[] = {
-    { "append_payload", 
-      (PyCFunction)xu_message_append_payload,
-      METH_VARARGS,
-      "Append @str to the message payload.\n" },
-
-    { "set_response_fields",
-      (PyCFunction)xu_message_set_response_fields,
-      METH_VARARGS,
-      "Fill in the response fields in a message that was passed to us.\n" },
-
-    { "get_payload",
-      (PyCFunction)xu_message_get_payload,
-      METH_VARARGS,
-      "Return the message payload in string form.\n" },
-
-    { "get_header",
-      (PyCFunction)xu_message_get_header,
-      METH_VARARGS,
-      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_message_type;
-
-static PyObject *xu_message_new(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum;
-    int type, subtype, id, dict_items_parsed = 0;
-    PyObject *payload = NULL;
-
-    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
-        return NULL;
-
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-
-    xum->msg.type    = type;
-    xum->msg.subtype = subtype;
-    xum->msg.id      = id;
-    xum->msg.length  = 0;
-
-    if ( payload == NULL )
-        return (PyObject *)xum;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    switch ( TYPE(type, subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(blkif_fe_interface_status_changed_t, handle, u32);
-        P2C(blkif_fe_interface_status_changed_t, status, u32);
-        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        P2C(blkif_be_create_t, domid,        u32);
-        P2C(blkif_be_create_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        P2C(blkif_be_destroy_t, domid,        u32);
-        P2C(blkif_be_destroy_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        P2C(blkif_be_connect_t, domid,        u32);
-        P2C(blkif_be_connect_t, blkif_handle, u32);
-        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
-        P2C(blkif_be_connect_t, evtchn,       u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        P2C(blkif_be_disconnect_t, domid,        u32);
-        P2C(blkif_be_disconnect_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        P2C(blkif_be_vbd_create_t, domid,        u32);
-        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
-        P2C(blkif_be_vbd_create_t, readonly,     u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        P2C(blkif_be_vbd_destroy_t, domid,        u32);
-        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
-        P2C(blkif_be_vbd_grow_t, domid,                u32);
-        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
-        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
-        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
-        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
-        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
-        P2C(blkif_be_vbd_shrink_t, domid,        u32);
-        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(netif_fe_interface_status_changed_t, handle, u32);
-        P2C(netif_fe_interface_status_changed_t, status, u32);
-        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
-        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        P2C(netif_be_create_t, domid,        u32);
-        P2C(netif_be_create_t, netif_handle, u32);
-        P2C(netif_be_create_t, mac[0],       u8);
-        P2C(netif_be_create_t, mac[1],       u8);
-        P2C(netif_be_create_t, mac[2],       u8);
-        P2C(netif_be_create_t, mac[3],       u8);
-        P2C(netif_be_create_t, mac[4],       u8);
-        P2C(netif_be_create_t, mac[5],       u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        P2C(netif_be_destroy_t, domid,        u32);
-        P2C(netif_be_destroy_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        P2C(netif_be_connect_t, domid,          u32);
-        P2C(netif_be_connect_t, netif_handle,   u32);
-        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
-        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
-        P2C(netif_be_connect_t, evtchn,         u16);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        P2C(netif_be_disconnect_t, domid,        u32);
-        P2C(netif_be_disconnect_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, status,        u32);
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_message_getattr(PyObject *obj, char *name)
-{
-    xu_message_object *xum;
-    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
-        return PyInt_FromLong(sizeof(xum->msg.msg));
-    return Py_FindMethod(xu_message_methods, obj, name);
-}
-
-static void xu_message_dealloc(PyObject *self)
-{
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_message_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "message",
-    sizeof(xu_message_object),
-    0,
-    xu_message_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_message_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** PORT ***********************
- */
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn)
-{
-    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
-                       MAP_SHARED, fd, pfn * PAGE_SIZE);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return (control_if_t *)(vaddr + 2048);
-}
-static void unmap_control_interface(int fd, control_if_t *c)
-{
-    char *vaddr = (char *)c - 2048;
-    (void)munmap(vaddr, PAGE_SIZE);
-}
-
-typedef struct xu_port_object {
-    PyObject_HEAD;
-    int mem_fd;
-    int xc_handle;
-    u32 remote_dom;
-    int local_port, remote_port;
-    control_if_t    *interface;
-    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
-    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
-} xu_port_object;
-
-static PyObject *port_error;
-
-static int xup_connect(xu_port_object *xup, domid_t dom,
-                       int local_port, int remote_port){
-    // From our prespective rx = producer, tx = consumer.
-    int err = 0;
-    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
-           local_port, remote_port);
-
-    // Consumer = tx.
-    //xup->interface->tx_resp_prod = 0;
-    //xup->interface->tx_req_prod = 0;
-    xup->tx_resp_prod = xup->interface->tx_resp_prod;
-    xup->tx_req_cons = xup->interface->tx_resp_prod;
-    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
-           (unsigned int)xup->interface->tx_resp_prod,
-           (unsigned int)xup->tx_resp_prod,
-           (unsigned int)xup->tx_req_cons,
-           (unsigned int)xup->interface->tx_req_prod);
-
-    // Producer = rx.
-    //xup->interface->rx_req_prod  = 0;
-    //xup->interface->rx_resp_prod = 0;
-    xup->rx_req_prod  = xup->interface->rx_req_prod;
-    xup->rx_resp_cons = xup->interface->rx_resp_prod;
-    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
-           (unsigned int)xup->rx_resp_cons,
-           (unsigned int)xup->interface->rx_resp_prod,
-           (unsigned int)xup->interface->rx_req_prod,
-           (unsigned int)xup->rx_req_prod);
-
-    xup->remote_dom   = dom;
-    xup->local_port   = local_port;
-    xup->remote_port  = remote_port;
-
-    printf("%s< err=%d\n", __FUNCTION__, err);
-    return err;
-}
-
-static PyObject *xu_port_notify(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   c = xup->tx_req_cons;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->tx_req_prod) || 
-         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
-    {
-        PyErr_SetString(port_error, "no request to read");
-        return NULL;
-    }
-
-    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    xup->tx_req_cons++;
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   p = xup->rx_req_prod;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
-        return NULL;        
-    }
-
-    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
-    {
-        PyErr_SetString(port_error, "no space to write request");
-        return NULL;
-    }
-
-    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
-    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
-    xup->rx_req_prod = cif->rx_req_prod = p + 1;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   c = xup->rx_resp_cons;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
-    {
-        PyErr_SetString(port_error, "no response to read");
-        return NULL;
-    }
-
-    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    xup->rx_resp_cons++;
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   p = xup->tx_resp_prod;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
-        return NULL;        
-    }
-
-    if ( p == xup->tx_req_cons )
-    {
-        PyErr_SetString(port_error, "no space to write response");
-        return NULL;
-    }
-
-    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
-    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
-    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   c = xup->tx_req_cons;
-    control_if_t      *cif = xup->interface;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->tx_req_prod) || 
-         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   p = xup->rx_req_prod;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   c = xup->rx_resp_cons;
-    control_if_t      *cif = xup->interface;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_response(
-    PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   p = xup->tx_resp_prod;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( p == xup->tx_req_cons )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyMethodDef xu_port_methods[] = {
-    { "notify",
-      (PyCFunction)xu_port_notify,
-      METH_VARARGS,
-      "Send a notification to the remote end.\n" },
-
-    { "read_request",
-      (PyCFunction)xu_port_read_request,
-      METH_VARARGS,
-      "Read a request message from the control interface.\n" },
-
-    { "write_request",
-      (PyCFunction)xu_port_write_request,
-      METH_VARARGS,
-      "Write a request message to the control interface.\n" },
-
-    { "read_response",
-      (PyCFunction)xu_port_read_response,
-      METH_VARARGS,
-      "Read a response message from the control interface.\n" },
-
-    { "write_response",
-      (PyCFunction)xu_port_write_response,
-      METH_VARARGS,
-      "Write a response message to the control interface.\n" },
-
-    { "request_to_read",
-      (PyCFunction)xu_port_request_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a request message to read.\n" },
-
-    { "space_to_write_request",
-      (PyCFunction)xu_port_space_to_write_request,
-      METH_VARARGS,
-      "Returns TRUE if there is space to write a request message.\n" },
-
-    { "response_to_read",
-      (PyCFunction)xu_port_response_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a response message to read.\n" },
-
-    { "space_to_write_response",
-      (PyCFunction)xu_port_space_to_write_response,
-      METH_VARARGS,
-      "Returns TRUE if there is space to write a response message.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_port_type;
-
-static PyObject *xu_port_new(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup;
-    u32 dom;
-    int port1, port2;
-    xc_dominfo_t info;
-
-    if ( !PyArg_ParseTuple(args, "i", &dom) )
-        return NULL;
-
-    xup = PyObject_New(xu_port_object, &xu_port_type);
-
-    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
-    {
-        PyErr_SetString(port_error, "Could not open '/dev/mem'");
-        goto fail1;
-    }
-
-    /* Set the General-Purpose Subject whose page frame will be mapped. */
-    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
-
-    if ( (xup->xc_handle = xc_interface_open()) == -1 )
-    {
-        PyErr_SetString(port_error, "Could not open Xen control interface");
-        goto fail2;
-    }
-
-    if ( dom == 0 )
-    {
-        /*
-         * The control-interface event channel for DOM0 is already set up.
-         * We use an ioctl to discover the port at our end of the channel.
-         */
-        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
-        port2 = -1; /* We don't need the remote end of the DOM0 link. */
-        if ( port1 < 0 )
-        {
-            PyErr_SetString(port_error, "Could not open channel to DOM0");
-            goto fail3;
-        }
-    }
-    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
-                                         DOMID_SELF, dom, 
-                                         &port1, &port2) != 0 )
-    {
-        PyErr_SetString(port_error, "Could not open channel to domain");
-        goto fail3;
-    }
-
-    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
-         (info.domid != dom) )
-    {
-        PyErr_SetString(port_error, "Failed to obtain domain status");
-        goto fail4;
-    }
-
-    xup->interface = 
-        map_control_interface(xup->mem_fd, info.shared_info_frame);
-    if ( xup->interface == NULL )
-    {
-        PyErr_SetString(port_error, "Failed to map domain control interface");
-        goto fail4;
-    }
-
-    xup_connect(xup, dom, port1, port2);
-    return (PyObject *)xup;
-
-    
- fail4:
-    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
- fail3:
-    (void)xc_interface_close(xup->xc_handle);
- fail2:
-    (void)close(xup->mem_fd);
- fail1:
-    PyObject_Del((PyObject *)xup);
-    return NULL;        
-}
-
-static PyObject *xu_port_getattr(PyObject *obj, char *name)
-{
-    xu_port_object *xup = (xu_port_object *)obj;
-    if ( strcmp(name, "local_port") == 0 )
-        return PyInt_FromLong(xup->local_port);
-    if ( strcmp(name, "remote_port") == 0 )
-        return PyInt_FromLong(xup->remote_port);
-    if ( strcmp(name, "remote_dom") == 0 )
-        return PyInt_FromLong(xup->remote_dom);
-    return Py_FindMethod(xu_port_methods, obj, name);
-}
-
-static void xu_port_dealloc(PyObject *self)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-    unmap_control_interface(xup->mem_fd, xup->interface);
-    if ( xup->remote_dom != 0 )
-        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
-    (void)xc_interface_close(xup->xc_handle);
-    (void)close(xup->mem_fd);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_port_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "port",
-    sizeof(xu_port_object),
-    0,
-    xu_port_dealloc,     /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_port_getattr,     /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** BUFFER ***********************
- */
-
-#define BUFSZ 65536
-#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
-typedef unsigned int BUF_IDX;
-
-typedef struct {
-    PyObject_HEAD;
-    char        *buf;
-    unsigned int prod, cons;
-} xu_buffer_object;
-
-static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
-{
-    PyObject *str1, *str2;
-    int len1, len2, c = MASK_BUF_IDX(xub->cons);
-
-    len1 = xub->prod - xub->cons;
-    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
-        len1 = BUFSZ - c;
-    if ( len1 > max )         /* clip to specified maximum */
-        len1 = max;
-    if ( len1 < 0 )           /* sanity */
-        len1 = 0;
-
-    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
-        return NULL;
-
-    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
-    {
-        len2 = max - len1;
-        if ( len2 > MASK_BUF_IDX(xub->prod) )
-            len2 = MASK_BUF_IDX(xub->prod);
-        if ( len2 > 0 )
-        {
-            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
-            if ( str2 == NULL )
-                return NULL;
-            PyString_ConcatAndDel(&str1, str2);
-            if ( str1 == NULL )
-                return NULL;
-        }
-    }
-
-    return str1;
-}
-
-static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-    
-    return __xu_buffer_peek(xub, max);
-}
-
-static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    PyObject *str;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-
-    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
-        xub->cons += PyString_Size(str);
-
-    return str;
-}
-
-static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max, len;
-
-    if ( !PyArg_ParseTuple(args, "i", &max) )
-        return NULL;
-
-    len = xub->prod - xub->cons;
-    if ( len > max )
-        len = max;
-    if ( len < 0 )
-        len = 0;
-
-    xub->cons += len;
-
-    return PyInt_FromLong(len);
-}
-
-static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    char *str;
-    int len, len1, len2;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    len1 = len;
-    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
-    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
-        len1 = BUFSZ - (xub->prod - xub->cons);
-
-    if ( len1 == 0 )
-        return PyInt_FromLong(0);
-
-    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
-    xub->prod += len1;
-
-    if ( len1 < len )
-    {
-        len2 = len - len1;
-        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
-        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
-            len2 = BUFSZ - (xub->prod - xub->cons);
-        if ( len2 != 0 )
-        {
-            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
-            xub->prod += len2;
-            return PyInt_FromLong(len1 + len2);
-        }
-    }
-
-    return PyInt_FromLong(len1);
-}
-
-static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xub->cons == xub->prod )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (xub->prod - xub->cons) == BUFSZ )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyMethodDef xu_buffer_methods[] = {
-    { "peek", 
-      (PyCFunction)xu_buffer_peek,
-      METH_VARARGS,
-      "Peek up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "read", 
-      (PyCFunction)xu_buffer_read,
-      METH_VARARGS,
-      "Read up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "discard", 
-      (PyCFunction)xu_buffer_discard,
-      METH_VARARGS,
-      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
-
-    { "write", 
-      (PyCFunction)xu_buffer_write,
-      METH_VARARGS,
-      "Write @string into buffer. Return number of bytes written.\n" },
-
-    { "empty", 
-      (PyCFunction)xu_buffer_empty,
-      METH_VARARGS,
-      "Return TRUE if the buffer is empty.\n" },
-
-    { "full", 
-      (PyCFunction)xu_buffer_full,
-      METH_VARARGS,
-      "Return TRUE if the buffer is full.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_buffer_type;
-
-static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
-
-    if ( (xub->buf = malloc(BUFSZ)) == NULL )
-    {
-        PyObject_Del((PyObject *)xub);
-        return NULL;
-    }
-
-    xub->prod = xub->cons = 0;
-
-    return (PyObject *)xub;
-}
-
-static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(xu_buffer_methods, obj, name);
-}
-
-static void xu_buffer_dealloc(PyObject *self)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    free(xub->buf);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_buffer_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "buffer",
-    sizeof(xu_buffer_object),
-    0,
-    xu_buffer_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_buffer_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MODULE WRAPPER ***********************
- */
-
-static void handle_child_death(int dummy)
-{
-    while ( waitpid(-1, NULL, WNOHANG) > 0 )
-        continue;
-}
-
-static PyObject *xu_autoreap(PyObject *self, PyObject *args)
-{
-    struct sigaction sa;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_handler = handle_child_death;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
-    (void)sigaction(SIGCHLD, &sa, NULL);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMethodDef xu_methods[] = {
-    { "notifier", xu_notifier_new, METH_VARARGS, 
-      "Create a new notifier." },
-    { "message", xu_message_new, METH_VARARGS, 
-      "Create a new communications message." },
-    { "port", xu_port_new, METH_VARARGS, 
-      "Create a new communications port." },
-    { "buffer", xu_buffer_new, METH_VARARGS, 
-      "Create a new ring buffer." },
-    { "autoreap", xu_autoreap, METH_VARARGS,
-      "Ensure that zombie children are automatically reaped by the OS." },
-    { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxu(void)
-{
-    PyObject *m, *d;
-
-    m = Py_InitModule(XENPKG, xu_methods);
-
-    d = PyModule_GetDict(m);
-    port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
-    PyDict_SetItemString(d, "PortError", port_error);
-}
diff --git a/tools/python/xen/lowlevel/__init__.py b/tools/python/xen/lowlevel/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
new file mode 100644 (file)
index 0000000..9cce7b0
--- /dev/null
@@ -0,0 +1,1184 @@
+/******************************************************************************
+ * Xc.c
+ * 
+ * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
+ */
+
+#include <Python.h>
+#include <xc.h>
+#include <zlib.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "xc_private.h"
+#include "gzip_stream.h"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+#define XENPKG "xen.lowlevel.xc"
+
+static PyObject *xc_error, *zero;
+
+typedef struct {
+    PyObject_HEAD;
+    int xc_handle;
+} XcObject;
+
+/*
+ * Definitions for the 'xc' object type.
+ */
+
+static PyObject *pyxc_domain_create(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    unsigned int mem_kb = 0;
+    char        *name   = "(anon)";
+    int          cpu = -1;
+    u32          dom;
+    int          ret;
+
+    static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list, 
+                                      &mem_kb, &name, &cpu) )
+        return NULL;
+
+    if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return PyInt_FromLong(dom);
+}
+
+static PyObject *pyxc_domain_pause(PyObject *self,
+                                   PyObject *args,
+                                   PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_unpause(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_destroy(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_pincpu(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    int cpu = -1;
+
+    static char *kwd_list[] = { "dom", "cpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &dom, &cpu) )
+        return NULL;
+
+    if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_getinfo(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    PyObject *list;
+
+    u32 first_dom = 0;
+    int max_doms = 1024, nr_doms, i;
+    xc_dominfo_t *info;
+
+    static char *kwd_list[] = { "first_dom", "max_doms", NULL };
+    
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
+                                      &first_dom, &max_doms) )
+        return NULL;
+
+    if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
+        return PyErr_NoMemory();
+
+    nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
+    
+    list = PyList_New(nr_doms);
+    for ( i = 0 ; i < nr_doms; i++ )
+    {
+        PyList_SetItem(
+            list, i, 
+            Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
+                          ",s:l,s:L,s:s,s:l,s:i}",
+                          "dom",       info[i].domid,
+                          "cpu",       info[i].cpu,
+                          "dying",     info[i].dying,
+                          "crashed",   info[i].crashed,
+                          "shutdown",  info[i].shutdown,
+                          "paused",    info[i].paused,
+                          "blocked",   info[i].blocked,
+                          "running",   info[i].running,
+                          "mem_kb",    info[i].nr_pages*4,
+                          "cpu_time",  info[i].cpu_time,
+                          "name",      info[i].name,
+                          "maxmem_kb", info[i].max_memkb,
+                          "shutdown_reason", info[i].shutdown_reason
+                ));
+    }
+
+    free(info);
+
+    return list;
+}
+
+static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
+{
+    int rc = -1;
+    int fd = -1;
+    int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
+    int open_mode = 0644;
+
+    printf("%s>\n", __FUNCTION__);
+
+    if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
+    {
+        xcio_perror(ctxt, "Could not open file for writing");
+        goto exit;
+    }
+
+    printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
+
+    /* Compression rate 1: we want speed over compression. 
+     * We're mainly going for those zero pages, after all.
+     */
+    ctxt->io = gzip_stream_fdopen(fd, "wb1");
+    if ( ctxt->io == NULL )
+    {
+        xcio_perror(ctxt, "Could not allocate compression state");
+        goto exit;
+    }
+
+    printf("%s> xc_linux_save...\n", __FUNCTION__);
+
+    rc = xc_linux_save(xc->xc_handle, ctxt);
+
+  exit:
+    if ( ctxt->io != NULL )
+        IOStream_close(ctxt->io);
+    if ( fd >= 0 )
+        close(fd);
+    unlink(state_file);
+    printf("%s> rc=%d\n", __FUNCTION__, rc);
+    return rc;
+}
+
+static PyObject *pyxc_linux_save(PyObject *self,
+                                 PyObject *args,
+                                 PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    char *state_file;
+    int progress = 1, debug = 0;
+    PyObject *val = NULL;
+    int rc = -1;
+    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
+
+    static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 
+                                      &ioctxt.domain,
+                                      &state_file,
+                                      &ioctxt.vmconfig,
+                                      &progress, 
+                                      &debug) )
+        goto exit;
+
+    ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
+
+    if ( progress )
+        ioctxt.flags |= XCFLAGS_VERBOSE;
+    if ( debug )
+        ioctxt.flags |= XCFLAGS_DEBUG;
+
+    if ( (state_file == NULL) || (state_file[0] == '\0') )
+        goto exit;
+    
+    rc = file_save(xc, &ioctxt, state_file);
+    if ( rc != 0 )
+    {
+        PyErr_SetFromErrno(xc_error);
+        goto exit;
+    } 
+
+    Py_INCREF(zero);
+    val = zero;
+
+  exit:
+    return val;
+}
+
+
+static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
+{
+    int rc = -1;
+
+    ioctxt->io = gzip_stream_fopen(state_file, "rb");
+    if ( ioctxt->io == NULL )
+    {
+        xcio_perror(ioctxt, "Could not open file for reading");
+        return rc;
+    }
+
+    rc = xc_linux_restore(xc->xc_handle, ioctxt);
+
+    IOStream_close(ioctxt->io);
+    
+    return rc;
+}
+
+static PyObject *pyxc_linux_restore(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    char *state_file;
+    int progress = 1, debug = 0;
+    PyObject *val = NULL;
+    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
+    int rc =-1;
+
+    static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list,
+                                      &ioctxt.domain,
+                                      &state_file,
+                                      &progress,
+                                      &debug) )
+        goto exit;
+
+    if ( progress )
+        ioctxt.flags |= XCFLAGS_VERBOSE;
+    if ( debug )
+        ioctxt.flags |= XCFLAGS_DEBUG;
+
+    if ( (state_file == NULL) || (state_file[0] == '\0') )
+        goto exit;
+
+    rc = file_restore(xc, &ioctxt, state_file);
+    if ( rc != 0 )
+    {
+        PyErr_SetFromErrno(xc_error);
+        goto exit;
+    }
+
+    val = Py_BuildValue("{s:i,s:s}",
+                        "dom", ioctxt.domain,
+                        "vmconfig", ioctxt.vmconfig);
+
+  exit:
+    return val;
+}
+
+static PyObject *pyxc_linux_build(PyObject *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32   dom;
+    char *image, *ramdisk = NULL, *cmdline = "";
+    int   control_evtchn, flags = 0;
+
+    static char *kwd_list[] = { "dom", "control_evtchn", 
+                                "image", "ramdisk", "cmdline", "flags",
+                                NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
+                                      &dom, &control_evtchn, 
+                                      &image, &ramdisk, &cmdline, &flags) )
+        return NULL;
+
+    if ( xc_linux_build(xc->xc_handle, dom, image,
+                        ramdisk, cmdline, control_evtchn, flags) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_netbsd_build(PyObject *self,
+                                   PyObject *args,
+                                   PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32   dom;
+    char *image, *ramdisk = NULL, *cmdline = "";
+    int   control_evtchn;
+
+    static char *kwd_list[] = { "dom", "control_evtchn",
+                                "image", "ramdisk", "cmdline", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
+                                      &dom, &control_evtchn,
+                                      &image, &ramdisk, &cmdline) )
+        return NULL;
+
+    if ( xc_netbsd_build(xc->xc_handle, dom, image, 
+                         cmdline, control_evtchn) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_bvtsched_global_set(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    unsigned long ctx_allow;
+
+    static char *kwd_list[] = { "ctx_allow", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
+        return NULL;
+
+    if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_bvtsched_global_get(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    
+    unsigned long ctx_allow;
+    
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+    
+    if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
+}
+
+static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32           dom;
+    unsigned long mcuadv, warp, warpl, warpu;
+
+    static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
+                                "warpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
+                                      &dom, &mcuadv, &warp, &warpl, &warpu) )
+        return NULL;
+
+    if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, 
+                                warp, warpl, warpu) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 dom;
+    unsigned long mcuadv, warp, warpl, warpu;
+    
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+    
+    if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
+                                &warpl, &warpu) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
+                         "domain", dom,
+                         "mcuadv", mcuadv,
+                         "warp",   warp,
+                         "warpl",  warpl,
+                         "warpu",  warpu);
+}
+
+static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
+                                              PyObject *args,
+                                              PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
+    int port1, port2;
+
+    static char *kwd_list[] = { "dom1", "dom2", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, 
+                                      &dom1, &dom2) )
+        return NULL;
+
+    if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, 
+                                    dom2, &port1, &port2) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:i}", 
+                         "port1", port1,
+                         "port2", port2);
+}
+
+static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    int virq, port;
+
+    static char *kwd_list[] = { "virq", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
+        return NULL;
+
+    if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return PyInt_FromLong(port);
+}
+
+static PyObject *pyxc_evtchn_close(PyObject *self,
+                                   PyObject *args,
+                                   PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom = DOMID_SELF;
+    int port;
+
+    static char *kwd_list[] = { "port", "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &port, &dom) )
+        return NULL;
+
+    if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_evtchn_send(PyObject *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    int port;
+
+    static char *kwd_list[] = { "port", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
+        return NULL;
+
+    if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_evtchn_status(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    PyObject *dict;
+
+    u32 dom = DOMID_SELF;
+    int port, ret;
+    xc_evtchn_status_t status;
+
+    static char *kwd_list[] = { "port", "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &port, &dom) )
+        return NULL;
+
+    ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
+    if ( ret != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    switch ( status.status )
+    {
+    case EVTCHNSTAT_closed:
+        dict = Py_BuildValue("{s:s}", 
+                             "status", "closed");
+        break;
+    case EVTCHNSTAT_unbound:
+        dict = Py_BuildValue("{s:s}", 
+                             "status", "unbound");
+        break;
+    case EVTCHNSTAT_interdomain:
+        dict = Py_BuildValue("{s:s,s:i,s:i}", 
+                             "status", "interdomain",
+                             "dom", status.u.interdomain.dom,
+                             "port", status.u.interdomain.port);
+        break;
+    case EVTCHNSTAT_pirq:
+        dict = Py_BuildValue("{s:s,s:i}", 
+                             "status", "pirq",
+                             "irq", status.u.pirq);
+        break;
+    case EVTCHNSTAT_virq:
+        dict = Py_BuildValue("{s:s,s:i}", 
+                             "status", "virq",
+                             "irq", status.u.virq);
+        break;
+    default:
+        dict = Py_BuildValue("{}");
+        break;
+    }
+    
+    return dict;
+}
+
+static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
+                                                PyObject *args,
+                                                PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 dom;
+    int bus, dev, func, enable, ret;
+
+    static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list, 
+                                      &dom, &bus, &dev, &func, &enable) )
+        return NULL;
+
+    ret = xc_physdev_pci_access_modify(
+        xc->xc_handle, dom, bus, dev, func, enable);
+    if ( ret != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_readconsolering(PyObject *self,
+                                      PyObject *args,
+                                      PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    unsigned int clear = 0;
+    char         str[32768];
+    int          ret;
+
+    static char *kwd_list[] = { "clear", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
+        return NULL;
+
+    ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
+    if ( ret < 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return PyString_FromStringAndSize(str, ret);
+}
+
+static PyObject *pyxc_physinfo(PyObject *self,
+                               PyObject *args,
+                               PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    xc_physinfo_t info;
+    
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xc_physinfo(xc->xc_handle, &info) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
+                         "ht_per_core", info.ht_per_core,
+                         "cores",       info.cores,
+                         "total_pages", info.total_pages,
+                         "free_pages",  info.free_pages,
+                         "cpu_khz",     info.cpu_khz);
+}
+
+static PyObject *pyxc_atropos_domain_set(PyObject *self,
+                                         PyObject *args,
+                                         PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 domid;
+    u64 period, slice, latency;
+    int xtratime;
+
+    static char *kwd_list[] = { "dom", "period", "slice", "latency",
+                                "xtratime", NULL };
+    
+    if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
+                                     &period, &slice, &latency, &xtratime) )
+        return NULL;
+   
+    if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
+                               latency, xtratime) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_atropos_domain_get(PyObject *self,
+                                         PyObject *args,
+                                         PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 domid;
+    u64 period, slice, latency;
+    int xtratime;
+    
+    static char *kwd_list[] = { "dom", NULL };
+
+    if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
+        return NULL;
+    
+    if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
+                                &slice, &latency, &xtratime ) )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
+                         "domain",  domid,
+                         "period",  period,
+                         "slice",   slice,
+                         "latency", latency,
+                         "xtratime", xtratime);
+}
+
+
+static PyObject *pyxc_rrobin_global_set(PyObject *self,
+                                        PyObject *args,
+                                        PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u64 slice;
+    
+    static char *kwd_list[] = { "slice", NULL };
+
+    if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
+        return NULL;
+    
+    if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_shadow_control(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    int op=0;
+
+    static char *kwd_list[] = { "dom", "op", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &dom, &op) )
+        return NULL;
+
+    if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_rrobin_global_get(PyObject *self,
+                                        PyObject *args,
+                                        PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u64 slice;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    return Py_BuildValue("{s:L}", "slice", slice);
+}
+
+static PyObject *pyxc_domain_setname(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 dom;
+    char *name;
+
+    static char *kwd_list[] = { "dom", "name", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list, 
+                                      &dom, &name) )
+        return NULL;
+
+    if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_setmaxmem(PyObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    unsigned long max_memkb;
+
+    static char *kwd_list[] = { "dom", "max_memkb", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
+                                      &dom, &max_memkb) )
+        return NULL;
+
+    if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+
+static PyMethodDef pyxc_methods[] = {
+    { "domain_create", 
+      (PyCFunction)pyxc_domain_create, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Create a new domain.\n"
+      " mem_kb [int, 0]:        Memory allocation, in kilobytes.\n"
+      " name   [str, '(anon)']: Informative textual name.\n\n"
+      "Returns: [int] new domain identifier; -1 on error.\n" },
+
+    { "domain_pause", 
+      (PyCFunction)pyxc_domain_pause, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Temporarily pause execution of a domain.\n"
+      " dom [int]: Identifier of domain to be paused.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_unpause", 
+      (PyCFunction)pyxc_domain_unpause, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "(Re)start execution of a domain.\n"
+      " dom [int]: Identifier of domain to be unpaused.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_destroy", 
+      (PyCFunction)pyxc_domain_destroy, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Destroy a domain.\n"
+      " dom [int]:    Identifier of domain to be destroyed.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_pincpu", 
+      (PyCFunction)pyxc_domain_pincpu, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Pin a domain to a specified CPU.\n"
+      " dom [int]:     Identifier of domain to be pinned.\n"
+      " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_getinfo", 
+      (PyCFunction)pyxc_domain_getinfo, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Get information regarding a set of domains, in increasing id order.\n"
+      " first_dom [int, 0]:    First domain to retrieve info about.\n"
+      " max_doms  [int, 1024]: Maximum number of domains to retrieve info"
+      " about.\n\n"
+      "Returns: [list of dicts] if list length is less than 'max_doms'\n"
+      "         parameter then there was an error, or the end of the\n"
+      "         domain-id space was reached.\n"
+      " dom      [int]: Identifier of domain to which this info pertains\n"
+      " cpu      [int]:  CPU to which this domain is bound\n"
+      " dying    [int]:  Bool - is the domain dying?\n"
+      " crashed  [int]:  Bool - has the domain crashed?\n"
+      " shutdown [int]:  Bool - has the domain shut itself down?\n"
+      " paused   [int]:  Bool - is the domain paused by control software?\n"
+      " blocked  [int]:  Bool - is the domain blocked waiting for an event?\n"
+      " running  [int]:  Bool - is the domain currently running?\n"
+      " mem_kb   [int]:  Memory reservation, in kilobytes\n"
+      " cpu_time [long]: CPU time consumed, in nanoseconds\n"
+      " name     [str]:  Identifying name\n"
+      " shutdown_reason [int]: Numeric code from guest OS, explaining "
+      "reason why it shut itself down.\n" },
+
+    { "linux_save", 
+      (PyCFunction)pyxc_linux_save, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Save the CPU and memory state of a Linux guest OS.\n"
+      " dom        [int]:    Identifier of domain to be saved.\n"
+      " state_file [str]:    Name of state file. Must not currently exist.\n"
+      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "linux_restore", 
+      (PyCFunction)pyxc_linux_restore, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Restore the CPU and memory state of a Linux guest OS.\n"
+      " state_file [str]:    Name of state file. Must not currently exist.\n"
+      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
+      "Returns: [int] new domain identifier on success; -1 on error.\n" },
+
+    { "linux_build", 
+      (PyCFunction)pyxc_linux_build, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Build a new Linux guest OS.\n"
+      " dom     [int]:      Identifier of domain to build into.\n"
+      " image   [str]:      Name of kernel image file. May be gzipped.\n"
+      " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
+      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "netbsd_build", 
+      (PyCFunction)pyxc_netbsd_build, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Build a new NetBSD guest OS.\n"
+      " dom     [int]:     Identifier of domain to build into.\n"
+      " image   [str]:      Name of kernel image file. May be gzipped.\n"
+      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "bvtsched_global_set",
+      (PyCFunction)pyxc_bvtsched_global_set,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
+      " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "bvtsched_global_get",
+      (PyCFunction)pyxc_bvtsched_global_get,
+      METH_KEYWORDS, "\n"
+      "Get global tuning parameters for BVT scheduler.\n"
+      "Returns: [dict]:\n"
+      " ctx_allow [int]: context switch allowance\n" },
+
+    { "bvtsched_domain_set",
+      (PyCFunction)pyxc_bvtsched_domain_set,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
+      " dom    [int]: Identifier of domain to be tuned.\n"
+      " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
+      " warp   [int]: How far to warp domain's EVT on unblock.\n"
+      " warpl  [int]: How long the domain can run warped.\n"
+      " warpu  [int]: How long before the domain can warp again.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "bvtsched_domain_get",
+      (PyCFunction)pyxc_bvtsched_domain_get,
+      METH_KEYWORDS, "\n"
+      "Get per-domain tuning parameters under the BVT scheduler.\n"
+      " dom [int]: Identifier of domain to be queried.\n"
+      "Returns [dict]:\n"
+      " domain [int]:  Domain ID.\n"
+      " mcuadv [long]: MCU Advance.\n"
+      " warp   [long]: Warp.\n"
+      " warpu  [long]: Unwarp requirement.\n"
+      " warpl  [long]: Warp limit,\n"
+    },
+
+    { "atropos_domain_set",
+      (PyCFunction)pyxc_atropos_domain_set,
+      METH_KEYWORDS, "\n"
+      "Set the scheduling parameters for a domain when running with Atropos.\n"
+      " dom      [int]:  domain to set\n"
+      " period   [long]: domain's scheduling period\n"
+      " slice    [long]: domain's slice per period\n"
+      " latency  [long]: wakeup latency hint\n"
+      " xtratime [int]: boolean\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "atropos_domain_get",
+      (PyCFunction)pyxc_atropos_domain_get,
+      METH_KEYWORDS, "\n"
+      "Get the current scheduling parameters for a domain when running with\n"
+      "the Atropos scheduler."
+      " dom      [int]: domain to query\n"
+      "Returns:  [dict]\n"
+      " domain   [int]: domain ID\n"
+      " period   [long]: scheduler period\n"
+      " slice    [long]: CPU reservation per period\n"
+      " latency  [long]: unblocking latency hint\n"
+      " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
+
+    { "rrobin_global_set",
+      (PyCFunction)pyxc_rrobin_global_set,
+      METH_KEYWORDS, "\n"
+      "Set Round Robin scheduler slice.\n"
+      " slice [long]: Round Robin scheduler slice\n"
+      "Returns: [int] 0 on success, throws an exception on failure\n" },
+
+    { "rrobin_global_get",
+      (PyCFunction)pyxc_rrobin_global_get,
+      METH_KEYWORDS, "\n"
+      "Get Round Robin scheduler settings\n"
+      "Returns [dict]:\n"
+      " slice  [long]: Scheduler time slice.\n" },    
+
+    { "evtchn_bind_interdomain", 
+      (PyCFunction)pyxc_evtchn_bind_interdomain, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Open an event channel between two domains.\n"
+      " dom1 [int, SELF]: First domain to be connected.\n"
+      " dom2 [int, SELF]: Second domain to be connected.\n\n"
+      "Returns: [dict] dictionary is empty on failure.\n"
+      " port1 [int]: Port-id for endpoint at dom1.\n"
+      " port2 [int]: Port-id for endpoint at dom2.\n" },
+
+    { "evtchn_bind_virq", 
+      (PyCFunction)pyxc_evtchn_bind_virq, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Bind an event channel to the specified VIRQ.\n"
+      " virq [int]: VIRQ to bind.\n\n"
+      "Returns: [int] Bound event-channel port.\n" },
+
+    { "evtchn_close", 
+      (PyCFunction)pyxc_evtchn_close, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Close an event channel.\n"
+      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
+      " port [int]:       Port-id of one endpoint of the channel.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "evtchn_send", 
+      (PyCFunction)pyxc_evtchn_send, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Send an event along a locally-connected event channel.\n"
+      " port [int]: Port-id of a local channel endpoint.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "evtchn_status", 
+      (PyCFunction)pyxc_evtchn_status, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Query the status of an event channel.\n"
+      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
+      " port [int]:       Port-id of one endpoint of the channel.\n\n"
+      "Returns: [dict] dictionary is empty on failure.\n"
+      " status [str]:  'closed', 'unbound', 'interdomain', 'pirq',"
+      " or 'virq'.\n"
+      "The following are returned if 'status' is 'interdomain':\n"
+      " dom  [int]: Dom-id of remote endpoint.\n"
+      " port [int]: Port-id of remote endpoint.\n"
+      "The following are returned if 'status' is 'pirq' or 'virq':\n"
+      " irq  [int]: IRQ number.\n" },
+
+    { "physdev_pci_access_modify",
+      (PyCFunction)pyxc_physdev_pci_access_modify,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Allow a domain access to a PCI device\n"
+      " dom    [int]: Identifier of domain to be allowed access.\n"
+      " bus    [int]: PCI bus\n"
+      " dev    [int]: PCI slot\n"
+      " func   [int]: PCI function\n"
+      " enable [int]: Non-zero means enable access; else disable access\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+    { "readconsolering", 
+      (PyCFunction)pyxc_readconsolering, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Read Xen's console ring.\n"
+      " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
+      "Returns: [str] string is empty on failure.\n" },
+
+    { "physinfo",
+      (PyCFunction)pyxc_physinfo,
+      METH_VARARGS, "\n"
+      "Get information about the physical host machine\n"
+      "Returns [dict]: information about the hardware"
+      "        [None]: on failure.\n" },
+
+    { "shadow_control", 
+      (PyCFunction)pyxc_shadow_control, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set parameter for shadow pagetable interface\n"
+      " dom [int]:   Identifier of domain.\n"
+      " op [int, 0]: operation\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_setname", 
+      (PyCFunction)pyxc_domain_setname, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set domain informative textual name\n"
+      " dom [int]:  Identifier of domain.\n"
+      " name [str]: Text string.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_setmaxmem", 
+      (PyCFunction)pyxc_domain_setmaxmem, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set a domain's memory limit\n"
+      " dom [int]: Identifier of domain.\n"
+      " max_memkb [long]: .\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+
+/*
+ * Definitions for the 'Xc' module wrapper.
+ */
+
+staticforward PyTypeObject PyXcType;
+
+static PyObject *PyXc_new(PyObject *self, PyObject *args)
+{
+    XcObject *xc;
+
+    if ( !PyArg_ParseTuple(args, ":new") )
+        return NULL;
+
+    xc = PyObject_New(XcObject, &PyXcType);
+
+    if ( (xc->xc_handle = xc_interface_open()) == -1 )
+    {
+        PyObject_Del((PyObject *)xc);
+        return PyErr_SetFromErrno(xc_error);
+    }
+
+    return (PyObject *)xc;
+}
+
+static PyObject *PyXc_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(pyxc_methods, obj, name);
+}
+
+static void PyXc_dealloc(PyObject *self)
+{
+    XcObject *xc = (XcObject *)self;
+    (void)xc_interface_close(xc->xc_handle);
+    PyObject_Del(self);
+}
+
+static PyTypeObject PyXcType = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "Xc",
+    sizeof(XcObject),
+    0,
+    PyXc_dealloc,    /* tp_dealloc     */
+    NULL,            /* tp_print       */
+    PyXc_getattr,    /* tp_getattr     */
+    NULL,            /* tp_setattr     */
+    NULL,            /* tp_compare     */
+    NULL,            /* tp_repr        */
+    NULL,            /* tp_as_number   */
+    NULL,            /* tp_as_sequence */
+    NULL,            /* tp_as_mapping  */
+    NULL             /* tp_hash        */
+};
+
+static PyMethodDef PyXc_methods[] = {
+    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
+    { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxc(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule(XENPKG, PyXc_methods);
+
+    d = PyModule_GetDict(m);
+    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
+    PyDict_SetItemString(d, "error", xc_error);
+
+    zero = PyInt_FromLong(0);
+}
diff --git a/tools/python/xen/lowlevel/xu/__init__.py b/tools/python/xen/lowlevel/xu/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/python/xen/lowlevel/xu/domain_controller.h b/tools/python/xen/lowlevel/xu/domain_controller.h
new file mode 100644 (file)
index 0000000..76dd164
--- /dev/null
@@ -0,0 +1,532 @@
+/******************************************************************************
+ * domain_controller.h
+ * 
+ * Interface to server controller (e.g., 'xend'). This header file defines the 
+ * interface that is shared with guest OSes.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __DOMAIN_CONTROLLER_H__
+#define __DOMAIN_CONTROLLER_H__
+
+
+#ifndef BASIC_START_INFO
+#error "Xen header file hypervisor-if.h must already be included here."
+#endif
+
+
+/*
+ * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
+ */
+
+typedef struct {
+    BASIC_START_INFO;
+    u16 domain_controller_evtchn; /* 320 */
+} PACKED extended_start_info_t; /* 322 bytes */
+#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
+#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
+
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
+ * interpreted by control software to determine the appropriate action. These 
+ * are only really advisories: the controller can actually do as it likes.
+ */
+#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
+#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
+
+
+/*
+ * CONTROLLER MESSAGING INTERFACE.
+ */
+
+typedef struct {
+    u8 type;     /*  0: echoed in response */
+    u8 subtype;  /*  1: echoed in response */
+    u8 id;       /*  2: echoed in response */
+    u8 length;   /*  3: number of bytes in 'msg' */
+    u8 msg[60];  /*  4: type-specific message data */
+} PACKED control_msg_t; /* 64 bytes */
+
+#define CONTROL_RING_SIZE 8
+typedef u32 CONTROL_RING_IDX;
+#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
+
+typedef struct {
+    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
+    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
+    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
+    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
+} PACKED control_if_t; /* 1040 bytes */
+
+/*
+ * Top-level command types.
+ */
+#define CMSG_CONSOLE        0  /* Console                 */
+#define CMSG_BLKIF_BE       1  /* Block-device backend    */
+#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
+#define CMSG_NETIF_BE       3  /* Network-device backend  */
+#define CMSG_NETIF_FE       4  /* Network-device frontend */
+#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
+
+
+/******************************************************************************
+ * CONSOLE DEFINITIONS
+ */
+
+/*
+ * Subtypes for console messages.
+ */
+#define CMSG_CONSOLE_DATA       0
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
+#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
+
+/* These are used by both front-end and back-end drivers. */
+#define blkif_vdev_t   u16
+#define blkif_pdev_t   u16
+#define blkif_sector_t u64
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its block interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32 handle; /*  0 */
+    u32 status; /*  4 */
+    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
+} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
+
+/*
+ * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define BLKIF_DRIVER_STATUS_DOWN   0
+#define BLKIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32 nr_interfaces; /*  4 */
+} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32      handle;      /*  0 */
+    u32      __pad;
+    memory_t shmem_frame; /*  8 */
+    MEMORY_PADDING;
+} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32 handle; /*  0 */
+} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
+#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
+#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
+#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
+#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
+#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
+
+/* Messages to domain controller. */
+#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for block-device messages.
+ */
+
+typedef struct {
+    blkif_sector_t sector_start;   /*  0 */
+    blkif_sector_t sector_length;  /*  8 */
+    blkif_pdev_t   device;         /* 16 */
+    u16            __pad;          /* 18 */
+} PACKED blkif_extent_t; /* 20 bytes */
+
+/* Non-specific 'okay' return. */
+#define BLKIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define BLKIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
+#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define BLKIF_BE_STATUS_VBD_EXISTS          5
+#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
+#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
+#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
+#define BLKIF_BE_STATUS_MAPPING_ERROR       9
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define BLKIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "VBD already exists",           \
+    "VBD not found",                \
+    "Out of memory",                \
+    "Extent not found for VBD",     \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_BLKIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_create_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
+    MEMORY_PADDING;
+    u32        evtchn;        /* 16: Event channel for notifications.    */
+    /* OUT */
+    u32        status;        /* 20 */
+} PACKED blkif_be_connect_t;  /* 24 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_disconnect_t; /* 12 bytes */
+
+/* CMSG_BLKIF_BE_VBD_CREATE */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
+    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_create_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_DESTROY */
+typedef struct {
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_GROW */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
+    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 30 */
+    /* OUT */
+    u32        status;        /* 32 */
+} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
+
+/* CMSG_BLKIF_BE_VBD_SHRINK */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the controller
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
+#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its network interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32        handle; /*  0 */
+    u32        status; /*  4 */
+    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
+    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
+} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
+
+/*
+ * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define NETIF_DRIVER_STATUS_DOWN   0
+#define NETIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32        nr_interfaces; /*  4 */
+} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32        handle;         /*  0 */
+    u32        __pad;          /*  4 */
+    memory_t   tx_shmem_frame; /*  8 */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16 */
+    MEMORY_PADDING;
+} PACKED netif_fe_interface_connect_t; /* 24 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32        handle;        /*  0 */
+} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
+#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
+#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+
+/* Messages to domain controller. */
+#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for net-device messages.
+ */
+
+/* Non-specific 'okay' return. */
+#define NETIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define NETIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
+#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
+#define NETIF_BE_STATUS_MAPPING_ERROR       6
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define NETIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "Out of memory",                \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_NETIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    u8         mac[6];        /*  8 */
+    u16        __pad;         /* 14 */
+    /* OUT */
+    u32        status;        /* 16 */
+} PACKED netif_be_create_t; /* 20 bytes */
+
+/*
+ * CMSG_NETIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        netif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32   status;             /*  8 */
+} PACKED netif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;          /*  0: Domain attached to new interface.   */
+    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
+    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
+    MEMORY_PADDING;
+    u16        evtchn;         /* 24: Event channel for notifications.    */
+    u16        __pad;          /* 26 */
+    /* OUT */
+    u32        status;         /* 28 */
+} PACKED netif_be_connect_t; /* 32 bytes */
+
+/*
+ * CMSG_NETIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED netif_be_disconnect_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * SHUTDOWN DEFINITIONS
+ */
+
+/*
+ * Subtypes for shutdown messages.
+ */
+#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
+#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
+#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
+                                    /* SHUTDOWN_suspend.                     */
+
+#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/python/xen/lowlevel/xu/xu.c b/tools/python/xen/lowlevel/xu/xu.c
new file mode 100644 (file)
index 0000000..ae11ce6
--- /dev/null
@@ -0,0 +1,1386 @@
+/******************************************************************************
+ * utils.c
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <xc.h>
+
+#include <hypervisor-if.h>
+#include "domain_controller.h"
+
+#include <asm-xen/proc_cmd.h>
+
+#define XENPKG "xen.lowlevel.xu"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 200
+#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
+#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
+#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
+/* /dev/xen/evtchn ioctls: */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET  _IO('E', 1)
+/* EVTCHN_BIND: Bind to teh specified event-channel port. */
+#define EVTCHN_BIND   _IO('E', 2)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IO('E', 3)
+
+/* Size of a machine page frame. */
+#define PAGE_SIZE 4096
+
+
+/*
+ * *********************** NOTIFIER ***********************
+ */
+
+typedef struct {
+    PyObject_HEAD;
+    int evtchn_fd;
+} xu_notifier_object;
+
+static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int bytes;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+    
+    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+    {
+        if ( errno == EINTR )
+            continue;
+        if ( errno == EAGAIN )
+            goto none;
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+    
+    if ( bytes == sizeof(v) )
+        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
+
+ none:
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    v = (u16)idx;
+    
+    (void)write(xun->evtchn_fd, &v, sizeof(v));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    return PyInt_FromLong(xun->evtchn_fd);
+}
+
+static PyMethodDef xu_notifier_methods[] = {
+    { "read",
+      (PyCFunction)xu_notifier_read,
+      METH_VARARGS,
+      "Read a (@port, @type) pair.\n" },
+
+    { "unmask", 
+      (PyCFunction)xu_notifier_unmask,
+      METH_VARARGS,
+      "Unmask notifications for a @port.\n" },
+
+    { "bind", 
+      (PyCFunction)xu_notifier_bind,
+      METH_VARARGS,
+      "Get notifications for a @port.\n" },
+
+    { "unbind", 
+      (PyCFunction)xu_notifier_unbind,
+      METH_VARARGS,
+      "No longer get notifications for a @port.\n" },
+
+    { "fileno", 
+      (PyCFunction)xu_notifier_fileno,
+      METH_VARARGS,
+      "Return the file descriptor for the notification channel.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_notifier_type;
+
+static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
+
+ reopen:
+    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+    if ( xun->evtchn_fd == -1 )
+    {
+        if ( (errno == ENOENT) &&
+             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
+                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
+            goto reopen;
+        PyObject_Del((PyObject *)xun);
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+
+    return (PyObject *)xun;
+}
+
+static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
+{
+    if ( strcmp(name, "EXCEPTION") == 0 )
+        return PyInt_FromLong(PORT_EXCEPTION);
+    if ( strcmp(name, "NORMAL") == 0 )
+        return PyInt_FromLong(PORT_NORMAL);
+    return Py_FindMethod(xu_notifier_methods, obj, name);
+}
+
+static void xu_notifier_dealloc(PyObject *self)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    (void)close(xun->evtchn_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_notifier_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "notifier",
+    sizeof(xu_notifier_object),
+    0,
+    xu_notifier_dealloc, /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_notifier_getattr, /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MESSAGE ***********************
+ */
+
+#define TYPE(_x,_y) (((_x)<<8)|(_y))
+#define P2C(_struct, _field, _ctype)                                      \
+    do {                                                                  \
+        PyObject *obj;                                                    \
+        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
+        {                                                                 \
+            if ( PyInt_Check(obj) )                                       \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyInt_AsLong(obj);                              \
+                dict_items_parsed++;                                      \
+            }                                                             \
+            else if ( PyLong_Check(obj) )                                 \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
+                dict_items_parsed++;                                      \
+            }                                                             \
+        }                                                                 \
+        xum->msg.length = sizeof(_struct);                                \
+    } while ( 0 )
+#define C2P(_struct, _field, _pytype, _ctype)                             \
+    do {                                                                  \
+        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
+                        (((_struct *)&xum->msg.msg[0])->_field);          \
+        if ( dict == NULL ) dict = PyDict_New();                          \
+        PyDict_SetItemString(dict, #_field, obj);                         \
+    } while ( 0 )
+
+typedef struct {
+    PyObject_HEAD;
+    control_msg_t msg;
+} xu_message_object;
+
+static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    char *str;
+    int len;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
+    {
+        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
+        return NULL;
+    }
+
+    memcpy(&xum->msg.msg[xum->msg.length], str, len);
+    xum->msg.length += len;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *payload;
+    int dict_items_parsed = 0;
+
+    if ( !PyArg_ParseTuple(args, "O", &payload) )
+        return NULL;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        return NULL;
+    }
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *dict = NULL;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
+        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
+        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
+        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        C2P(blkif_be_create_t, domid,        Int, Long);
+        C2P(blkif_be_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        C2P(blkif_be_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        C2P(blkif_be_connect_t, domid,        Int, Long);
+        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
+        C2P(blkif_be_connect_t, evtchn,       Int, Long);
+        C2P(blkif_be_connect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        C2P(blkif_be_disconnect_t, domid,        Int, Long);
+        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
+        C2P(blkif_be_vbd_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
+        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
+        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
+        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
+        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
+        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
+        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
+        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
+        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        C2P(netif_be_create_t, domid,        Int, Long);
+        C2P(netif_be_create_t, netif_handle, Int, Long);
+        C2P(netif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        C2P(netif_be_destroy_t, domid,        Int, Long);
+        C2P(netif_be_destroy_t, netif_handle, Int, Long);
+        C2P(netif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        C2P(netif_be_connect_t, domid,          Int, Long);
+        C2P(netif_be_connect_t, netif_handle,   Int, Long);
+        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, evtchn,         Int, Long);
+        C2P(netif_be_connect_t, status,         Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        C2P(netif_be_disconnect_t, domid,        Int, Long);
+        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
+        C2P(netif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(netif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    }
+
+    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
+}
+
+static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    return Py_BuildValue("{s:i,s:i,s:i}",
+                         "type",    xum->msg.type,
+                         "subtype", xum->msg.subtype,
+                         "id",      xum->msg.id);
+}
+
+static PyMethodDef xu_message_methods[] = {
+    { "append_payload", 
+      (PyCFunction)xu_message_append_payload,
+      METH_VARARGS,
+      "Append @str to the message payload.\n" },
+
+    { "set_response_fields",
+      (PyCFunction)xu_message_set_response_fields,
+      METH_VARARGS,
+      "Fill in the response fields in a message that was passed to us.\n" },
+
+    { "get_payload",
+      (PyCFunction)xu_message_get_payload,
+      METH_VARARGS,
+      "Return the message payload in string form.\n" },
+
+    { "get_header",
+      (PyCFunction)xu_message_get_header,
+      METH_VARARGS,
+      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_message_type;
+
+static PyObject *xu_message_new(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum;
+    int type, subtype, id, dict_items_parsed = 0;
+    PyObject *payload = NULL;
+
+    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
+        return NULL;
+
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+
+    xum->msg.type    = type;
+    xum->msg.subtype = subtype;
+    xum->msg.id      = id;
+    xum->msg.length  = 0;
+
+    if ( payload == NULL )
+        return (PyObject *)xum;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    switch ( TYPE(type, subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(blkif_fe_interface_status_changed_t, handle, u32);
+        P2C(blkif_fe_interface_status_changed_t, status, u32);
+        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        P2C(blkif_be_create_t, domid,        u32);
+        P2C(blkif_be_create_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        P2C(blkif_be_destroy_t, domid,        u32);
+        P2C(blkif_be_destroy_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        P2C(blkif_be_connect_t, domid,        u32);
+        P2C(blkif_be_connect_t, blkif_handle, u32);
+        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
+        P2C(blkif_be_connect_t, evtchn,       u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        P2C(blkif_be_disconnect_t, domid,        u32);
+        P2C(blkif_be_disconnect_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        P2C(blkif_be_vbd_create_t, domid,        u32);
+        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
+        P2C(blkif_be_vbd_create_t, readonly,     u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        P2C(blkif_be_vbd_destroy_t, domid,        u32);
+        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        P2C(blkif_be_vbd_grow_t, domid,                u32);
+        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
+        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        P2C(blkif_be_vbd_shrink_t, domid,        u32);
+        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(netif_fe_interface_status_changed_t, handle, u32);
+        P2C(netif_fe_interface_status_changed_t, status, u32);
+        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
+        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        P2C(netif_be_create_t, domid,        u32);
+        P2C(netif_be_create_t, netif_handle, u32);
+        P2C(netif_be_create_t, mac[0],       u8);
+        P2C(netif_be_create_t, mac[1],       u8);
+        P2C(netif_be_create_t, mac[2],       u8);
+        P2C(netif_be_create_t, mac[3],       u8);
+        P2C(netif_be_create_t, mac[4],       u8);
+        P2C(netif_be_create_t, mac[5],       u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        P2C(netif_be_destroy_t, domid,        u32);
+        P2C(netif_be_destroy_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        P2C(netif_be_connect_t, domid,          u32);
+        P2C(netif_be_connect_t, netif_handle,   u32);
+        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, evtchn,         u16);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        P2C(netif_be_disconnect_t, domid,        u32);
+        P2C(netif_be_disconnect_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, status,        u32);
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_message_getattr(PyObject *obj, char *name)
+{
+    xu_message_object *xum;
+    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
+        return PyInt_FromLong(sizeof(xum->msg.msg));
+    return Py_FindMethod(xu_message_methods, obj, name);
+}
+
+static void xu_message_dealloc(PyObject *self)
+{
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_message_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "message",
+    sizeof(xu_message_object),
+    0,
+    xu_message_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_message_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** PORT ***********************
+ */
+
+static control_if_t *map_control_interface(int fd, unsigned long pfn)
+{
+    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, fd, pfn * PAGE_SIZE);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return (control_if_t *)(vaddr + 2048);
+}
+static void unmap_control_interface(int fd, control_if_t *c)
+{
+    char *vaddr = (char *)c - 2048;
+    (void)munmap(vaddr, PAGE_SIZE);
+}
+
+typedef struct xu_port_object {
+    PyObject_HEAD;
+    int mem_fd;
+    int xc_handle;
+    u32 remote_dom;
+    int local_port, remote_port;
+    control_if_t    *interface;
+    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+} xu_port_object;
+
+static PyObject *port_error;
+
+static int xup_connect(xu_port_object *xup, domid_t dom,
+                       int local_port, int remote_port){
+    // From our prespective rx = producer, tx = consumer.
+    int err = 0;
+    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
+           local_port, remote_port);
+
+    // Consumer = tx.
+    //xup->interface->tx_resp_prod = 0;
+    //xup->interface->tx_req_prod = 0;
+    xup->tx_resp_prod = xup->interface->tx_resp_prod;
+    xup->tx_req_cons = xup->interface->tx_resp_prod;
+    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->interface->tx_resp_prod,
+           (unsigned int)xup->tx_resp_prod,
+           (unsigned int)xup->tx_req_cons,
+           (unsigned int)xup->interface->tx_req_prod);
+
+    // Producer = rx.
+    //xup->interface->rx_req_prod  = 0;
+    //xup->interface->rx_resp_prod = 0;
+    xup->rx_req_prod  = xup->interface->rx_req_prod;
+    xup->rx_resp_cons = xup->interface->rx_resp_prod;
+    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->rx_resp_cons,
+           (unsigned int)xup->interface->rx_resp_prod,
+           (unsigned int)xup->interface->rx_req_prod,
+           (unsigned int)xup->rx_req_prod);
+
+    xup->remote_dom   = dom;
+    xup->local_port   = local_port;
+    xup->remote_port  = remote_port;
+
+    printf("%s< err=%d\n", __FUNCTION__, err);
+    return err;
+}
+
+static PyObject *xu_port_notify(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no request to read");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->tx_req_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+        return NULL;        
+    }
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no space to write request");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->rx_req_prod = cif->rx_req_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+    {
+        PyErr_SetString(port_error, "no response to read");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->rx_resp_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+        return NULL;        
+    }
+
+    if ( p == xup->tx_req_cons )
+    {
+        PyErr_SetString(port_error, "no space to write response");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_response(
+    PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( p == xup->tx_req_cons )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyMethodDef xu_port_methods[] = {
+    { "notify",
+      (PyCFunction)xu_port_notify,
+      METH_VARARGS,
+      "Send a notification to the remote end.\n" },
+
+    { "read_request",
+      (PyCFunction)xu_port_read_request,
+      METH_VARARGS,
+      "Read a request message from the control interface.\n" },
+
+    { "write_request",
+      (PyCFunction)xu_port_write_request,
+      METH_VARARGS,
+      "Write a request message to the control interface.\n" },
+
+    { "read_response",
+      (PyCFunction)xu_port_read_response,
+      METH_VARARGS,
+      "Read a response message from the control interface.\n" },
+
+    { "write_response",
+      (PyCFunction)xu_port_write_response,
+      METH_VARARGS,
+      "Write a response message to the control interface.\n" },
+
+    { "request_to_read",
+      (PyCFunction)xu_port_request_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a request message to read.\n" },
+
+    { "space_to_write_request",
+      (PyCFunction)xu_port_space_to_write_request,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a request message.\n" },
+
+    { "response_to_read",
+      (PyCFunction)xu_port_response_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a response message to read.\n" },
+
+    { "space_to_write_response",
+      (PyCFunction)xu_port_space_to_write_response,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a response message.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_port_type;
+
+static PyObject *xu_port_new(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup;
+    u32 dom;
+    int port1, port2;
+    xc_dominfo_t info;
+
+    if ( !PyArg_ParseTuple(args, "i", &dom) )
+        return NULL;
+
+    xup = PyObject_New(xu_port_object, &xu_port_type);
+
+    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open '/dev/mem'");
+        goto fail1;
+    }
+
+    /* Set the General-Purpose Subject whose page frame will be mapped. */
+    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
+
+    if ( (xup->xc_handle = xc_interface_open()) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open Xen control interface");
+        goto fail2;
+    }
+
+    if ( dom == 0 )
+    {
+        /*
+         * The control-interface event channel for DOM0 is already set up.
+         * We use an ioctl to discover the port at our end of the channel.
+         */
+        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
+        port2 = -1; /* We don't need the remote end of the DOM0 link. */
+        if ( port1 < 0 )
+        {
+            PyErr_SetString(port_error, "Could not open channel to DOM0");
+            goto fail3;
+        }
+    }
+    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
+                                         DOMID_SELF, dom, 
+                                         &port1, &port2) != 0 )
+    {
+        PyErr_SetString(port_error, "Could not open channel to domain");
+        goto fail3;
+    }
+
+    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
+         (info.domid != dom) )
+    {
+        PyErr_SetString(port_error, "Failed to obtain domain status");
+        goto fail4;
+    }
+
+    xup->interface = 
+        map_control_interface(xup->mem_fd, info.shared_info_frame);
+    if ( xup->interface == NULL )
+    {
+        PyErr_SetString(port_error, "Failed to map domain control interface");
+        goto fail4;
+    }
+
+    xup_connect(xup, dom, port1, port2);
+    return (PyObject *)xup;
+
+    
+ fail4:
+    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
+ fail3:
+    (void)xc_interface_close(xup->xc_handle);
+ fail2:
+    (void)close(xup->mem_fd);
+ fail1:
+    PyObject_Del((PyObject *)xup);
+    return NULL;        
+}
+
+static PyObject *xu_port_getattr(PyObject *obj, char *name)
+{
+    xu_port_object *xup = (xu_port_object *)obj;
+    if ( strcmp(name, "local_port") == 0 )
+        return PyInt_FromLong(xup->local_port);
+    if ( strcmp(name, "remote_port") == 0 )
+        return PyInt_FromLong(xup->remote_port);
+    if ( strcmp(name, "remote_dom") == 0 )
+        return PyInt_FromLong(xup->remote_dom);
+    return Py_FindMethod(xu_port_methods, obj, name);
+}
+
+static void xu_port_dealloc(PyObject *self)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+    unmap_control_interface(xup->mem_fd, xup->interface);
+    if ( xup->remote_dom != 0 )
+        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
+    (void)xc_interface_close(xup->xc_handle);
+    (void)close(xup->mem_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_port_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "port",
+    sizeof(xu_port_object),
+    0,
+    xu_port_dealloc,     /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_port_getattr,     /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** BUFFER ***********************
+ */
+
+#define BUFSZ 65536
+#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
+typedef unsigned int BUF_IDX;
+
+typedef struct {
+    PyObject_HEAD;
+    char        *buf;
+    unsigned int prod, cons;
+} xu_buffer_object;
+
+static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
+{
+    PyObject *str1, *str2;
+    int len1, len2, c = MASK_BUF_IDX(xub->cons);
+
+    len1 = xub->prod - xub->cons;
+    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
+        len1 = BUFSZ - c;
+    if ( len1 > max )         /* clip to specified maximum */
+        len1 = max;
+    if ( len1 < 0 )           /* sanity */
+        len1 = 0;
+
+    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
+        return NULL;
+
+    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
+    {
+        len2 = max - len1;
+        if ( len2 > MASK_BUF_IDX(xub->prod) )
+            len2 = MASK_BUF_IDX(xub->prod);
+        if ( len2 > 0 )
+        {
+            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
+            if ( str2 == NULL )
+                return NULL;
+            PyString_ConcatAndDel(&str1, str2);
+            if ( str1 == NULL )
+                return NULL;
+        }
+    }
+
+    return str1;
+}
+
+static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+    
+    return __xu_buffer_peek(xub, max);
+}
+
+static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    PyObject *str;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+
+    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
+        xub->cons += PyString_Size(str);
+
+    return str;
+}
+
+static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max, len;
+
+    if ( !PyArg_ParseTuple(args, "i", &max) )
+        return NULL;
+
+    len = xub->prod - xub->cons;
+    if ( len > max )
+        len = max;
+    if ( len < 0 )
+        len = 0;
+
+    xub->cons += len;
+
+    return PyInt_FromLong(len);
+}
+
+static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    char *str;
+    int len, len1, len2;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    len1 = len;
+    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
+    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
+        len1 = BUFSZ - (xub->prod - xub->cons);
+
+    if ( len1 == 0 )
+        return PyInt_FromLong(0);
+
+    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
+    xub->prod += len1;
+
+    if ( len1 < len )
+    {
+        len2 = len - len1;
+        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
+        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
+            len2 = BUFSZ - (xub->prod - xub->cons);
+        if ( len2 != 0 )
+        {
+            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
+            xub->prod += len2;
+            return PyInt_FromLong(len1 + len2);
+        }
+    }
+
+    return PyInt_FromLong(len1);
+}
+
+static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xub->cons == xub->prod )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (xub->prod - xub->cons) == BUFSZ )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyMethodDef xu_buffer_methods[] = {
+    { "peek", 
+      (PyCFunction)xu_buffer_peek,
+      METH_VARARGS,
+      "Peek up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "read", 
+      (PyCFunction)xu_buffer_read,
+      METH_VARARGS,
+      "Read up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "discard", 
+      (PyCFunction)xu_buffer_discard,
+      METH_VARARGS,
+      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
+
+    { "write", 
+      (PyCFunction)xu_buffer_write,
+      METH_VARARGS,
+      "Write @string into buffer. Return number of bytes written.\n" },
+
+    { "empty", 
+      (PyCFunction)xu_buffer_empty,
+      METH_VARARGS,
+      "Return TRUE if the buffer is empty.\n" },
+
+    { "full", 
+      (PyCFunction)xu_buffer_full,
+      METH_VARARGS,
+      "Return TRUE if the buffer is full.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_buffer_type;
+
+static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
+
+    if ( (xub->buf = malloc(BUFSZ)) == NULL )
+    {
+        PyObject_Del((PyObject *)xub);
+        return NULL;
+    }
+
+    xub->prod = xub->cons = 0;
+
+    return (PyObject *)xub;
+}
+
+static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(xu_buffer_methods, obj, name);
+}
+
+static void xu_buffer_dealloc(PyObject *self)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    free(xub->buf);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_buffer_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "buffer",
+    sizeof(xu_buffer_object),
+    0,
+    xu_buffer_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_buffer_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MODULE WRAPPER ***********************
+ */
+
+static void handle_child_death(int dummy)
+{
+    while ( waitpid(-1, NULL, WNOHANG) > 0 )
+        continue;
+}
+
+static PyObject *xu_autoreap(PyObject *self, PyObject *args)
+{
+    struct sigaction sa;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = handle_child_death;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+    (void)sigaction(SIGCHLD, &sa, NULL);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef xu_methods[] = {
+    { "notifier", xu_notifier_new, METH_VARARGS, 
+      "Create a new notifier." },
+    { "message", xu_message_new, METH_VARARGS, 
+      "Create a new communications message." },
+    { "port", xu_port_new, METH_VARARGS, 
+      "Create a new communications port." },
+    { "buffer", xu_buffer_new, METH_VARARGS, 
+      "Create a new ring buffer." },
+    { "autoreap", xu_autoreap, METH_VARARGS,
+      "Ensure that zombie children are automatically reaped by the OS." },
+    { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxu(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule(XENPKG, xu_methods);
+
+    d = PyModule_GetDict(m);
+    port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
+    PyDict_SetItemString(d, "PortError", port_error);
+}
index 4420c388f237213ec4461900d9f0edbdf09348b4..440b6275623e89ffe3db4c57555b93191ae0899a 100644 (file)
@@ -1,8 +1,8 @@
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 
 import socket
-import xen.ext.xc
-xc = xen.ext.xc.new()
+import xen.lowlevel.xc
+xc = xen.lowlevel.xc.new()
 
 import sxp
 import XendRoot
index 3aaf080c36a780d3528e354d64c35048b7dc5615..328450a6b5753693389b0165f1750ceb53c8deaf 100644 (file)
@@ -8,7 +8,7 @@ import sys
 
 from twisted.internet import defer
 
-import xen.ext.xc; xc = xen.ext.xc.new()
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
 
 import sxp
 import XendRoot
@@ -36,7 +36,6 @@ class XendDomain:
         self.xconsole = XendConsole.instance()
         # Table of domain info indexed by domain id.
         self.db = XendDB.XendDB(self.dbpath)
-        #self.domain = {}
         self.domain_db = self.db.fetchall("")
         if xroot.get_rebooted():
             print 'XendDomain> rebooted: removing all domain info'
@@ -45,6 +44,8 @@ class XendDomain:
         self.initial_refresh()
 
     def onVirq(self, event, val):
+        """Event handler for virq.
+        """
         print 'XendDomain> virq', val
         self.reap()
 
@@ -102,28 +103,12 @@ class XendDomain:
 
     def _new_domain(self, savedinfo, info):
         """Create a domain entry from saved info.
+
+        savedinfo saved info from the db
+        info      domain info from xen
+
+        returns deferred
         """
-##         console = None
-##         kernel = None
-##         id = sxp.child_value(info, 'id')
-##         dom = int(id)
-##         name = sxp.child_value(info, 'name')
-##         memory = int(sxp.child_value(info, 'memory'))
-##         consoleinfo = sxp.child(info, 'console')
-##         if consoleinfo:
-##             consoleid = sxp.child_value(consoleinfo, 'id')
-##             console = self.xconsole.console_get(consoleid)
-##         if dom and console is None:
-##             # Try to connect a console.
-##             console = self.xconsole.console_create(dom)
-##         config = sxp.child(info, 'config')
-##         if config:
-##             image = sxp.child(info, 'image')
-##             if image:
-##                 image = sxp.child0(image)
-##                 kernel = sxp.child_value(image, 'kernel')
-##         dominfo = XendDomainInfo.XendDomainInfo(
-##             config, dom, name, memory, kernel, console)
         config = sxp.child_value(savedinfo, 'config')
         deferred = XendDomainInfo.vm_recreate(config, info)
         def fn(dominfo):
@@ -132,12 +117,23 @@ class XendDomain:
         return deferred
 
     def _add_domain(self, id, info, notify=1):
+        """Add a domain entry to the tables.
+
+        id     domain id
+        info   domain info object
+        notify send a domain created event if true
+        """
         self.domain[id] = info
         self.domain_db[id] = info.sxpr()
         self.sync_domain(id)
         if notify: eserver.inject('xend.domain.created', id)
 
     def _delete_domain(self, id, notify=1):
+        """Remove a domain from the tables.
+
+        id     domain id
+        notify send a domain died event if true
+        """
         if id in self.domain:
             if notify: eserver.inject('xend.domain.died', id)
             del self.domain[id]
@@ -146,14 +142,13 @@ class XendDomain:
             self.db.delete(id)
 
     def reap(self):
-        """Go through the domains looking for ones that have crashed or stopped.
+        """Look for domains that have crashed or stopped.
         Tidy them up.
         """
         print 'XendDomain>reap>'
         domlist = xc.domain_getinfo()
         casualties = []
         for d in domlist:
-            #print 'dom', d
             dead = 0
             dead = dead or (d['crashed'] or d['shutdown'])
             dead = dead or (d['dying'] and
@@ -163,9 +158,6 @@ class XendDomain:
         for d in casualties:
             id = str(d['dom'])
             print 'XendDomain>reap> died id=', id, d
-            dominfo = self.domain.get(id)
-            if not dominfo: continue
-            dominfo.died()
             self.domain_destroy(id, refresh=0)
         print 'XendDomain>reap<'
 
@@ -181,9 +173,6 @@ class XendDomain:
             doms[id] = d
             if id not in self.domain:
                 config = None
-                #image = None
-                #newinfo = XendDomainInfo.XendDomainInfo(
-                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
                 deferred = XendDomainInfo.vm_recreate(config, d)
                 def fn(dominfo):
                     self._add_domain(dominfo.id, dominfo)
@@ -198,6 +187,10 @@ class XendDomain:
         self.reap()
 
     def refresh_domain(self, id):
+        """Refresh information for a single domain.
+
+        id domain id
+        """
         dom = int(id)
         dominfo = xc.domain_getinfo(dom, 1)
         if dominfo == [] or dominfo[0]['dom'] != dom:
@@ -213,17 +206,28 @@ class XendDomain:
                 d.update(dominfo[0])
 
     def domain_ls(self):
-        # List domains.
-        # Update info from kernel first.
+        """Get list of domain ids.
+
+        return domain ids
+        """
         self.refresh()
         return self.domain.keys()
 
     def domains(self):
+        """Get list of domain objects.
+
+        return domain objects
+        """
         self.refresh()
         return self.domain.values()
     
     def domain_create(self, config):
-        # Create domain, log it.
+        """Create a domain from a configuration.
+
+        config configuration
+
+        returns deferred
+        """
         deferred = XendDomainInfo.vm_create(config)
         def fn(dominfo):
             self._add_domain(dominfo.id, dominfo)
@@ -232,12 +236,19 @@ class XendDomain:
         return deferred
     
     def domain_get(self, id):
+        """Get up-to-date info about a domain.
+
+        id domain id
+        returns domain object (or None)
+        """
         id = str(id)
         self.refresh_domain(id)
         return self.domain.get(id)
     
     def domain_unpause(self, id):
-        """(Re)start domain running.
+        """Unpause domain execution.
+
+        id domain id
         """
         dom = int(id)
         eserver.inject('xend.domain.unpause', id)
@@ -245,6 +256,8 @@ class XendDomain:
     
     def domain_pause(self, id):
         """Pause domain execution.
+
+        id domain id
         """
         dom = int(id)
         eserver.inject('xend.domain.pause', id)
@@ -252,6 +265,9 @@ class XendDomain:
     
     def domain_shutdown(self, id, reason='poweroff'):
         """Shutdown domain (nicely).
+
+        id     domain id
+        reason shutdown type: poweroff, reboot, halt
         """
         dom = int(id)
         if dom <= 0:
@@ -263,23 +279,37 @@ class XendDomain:
     
     def domain_destroy(self, id, refresh=1):
         """Terminate domain immediately.
+
+        id domain id
+        refresh send a domain destroy event if true
         """
         dom = int(id)
         if dom <= 0:
             return 0
         eserver.inject('xend.domain.destroy', id)
-        val = xc.domain_destroy(dom=dom)
+        dominfo = self.domain.get(id)
+        if dominfo:
+            val = dominfo.destroy()
+        else:
+            val = xc.domain_destroy(dom=dom)
         if refresh: self.refresh()
         return val       
 
     def domain_migrate(self, id, dst):
         """Start domain migration.
+
+        id domain id
         """
         # Need a cancel too?
         pass
 
     def domain_save(self, id, dst, progress=0):
-        """Save domain state to file, destroy domain.
+        """Save domain state to file, destroy domain on success.
+        Leave domain running on error.
+
+        id       domain id
+        dst      destination file
+        progress output progress if true
         """
         dom = int(id)
         dominfo = self.domain_get(id)
@@ -288,79 +318,140 @@ class XendDomain:
         vmconfig = sxp.to_string(dominfo.sxpr())
         self.domain_pause(id)
         eserver.inject('xend.domain.save', id)
-        rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress)
+        try:
+            rc = xc.linux_save(dom=dom, state_file=dst,
+                               vmconfig=vmconfig, progress=progress)
+        except:
+            rc = -1
         if rc == 0:
             self.domain_destroy(id)
+        else:
+            self.domain_unpause(id)
         return rc
     
     def domain_restore(self, src, progress=0):
         """Restore domain from file.
+
+        src      source file
+        progress output progress if true
+
+        returns domain object
         """
         dominfo = XendDomainInfo.vm_restore(src, progress=progress)
         self._add_domain(dominfo.id, dominfo)
         return dominfo
     
-    #============================================================================
-    # Backward compatibility stuff from here on.
-
     def domain_pincpu(self, dom, cpu):
+        """Pin a domain to a cpu.
+
+        dom domain
+        cpu cpu number
+        """
         dom = int(dom)
         return xc.domain_pincpu(dom, cpu)
 
     def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
+        """Set BVT (Borrowed Virtual Time) scheduler parameters for a domain.
+        """
         dom = int(dom)
         return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
                                       warp=warp, warpl=warpl, warpu=warpu)
 
     def domain_cpu_bvt_get(self, dom):
+        """Get BVT (Borrowed Virtual Time) scheduler parameters for a domain.
+        """
         dom = int(dom)
         return xc.bvtsched_domain_get(dom)
     
     def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
+        """Set Atropos scheduler parameters for a domain.
+        """
         dom = int(dom)
         return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
 
     def domain_cpu_atropos_get(self, dom):
+        """Get Atropos scheduler parameters for a domain.
+        """
         dom = int(dom)
         return xc.atropos_domain_get(dom)
 
-    def domain_vif_ls(self, dom):
+    def domain_devtype_ls(self, dom, type):
+        """Get list of device indexes for a domain.
+
+        dom  domain
+        type device type
+
+        returns device indexes
+        """
         dominfo = self.domain_get(dom)
         if not dominfo: return None
-        devs = dominfo.get_devices('vif')
+        devs = dominfo.get_devices(type)
         return range(0, len(devs))
 
-    def domain_vif_get(self, dom, vif):
+    def domain_devtype_get(self, dom, type, idx):
+        """Get a device from a domain.
+
+        dom  domain
+        type device type
+        idx  device index
+
+        returns device object (or None)
+        """
         dominfo = self.domain_get(dom)
         if not dominfo: return None
-        return dominfo.get_device_by_index(vif)
+        return dominfo.get_device_by_index(type, idx)
+
+    def domain_vif_ls(self, dom):
+        """Get list of virtual network interface (vif) indexes for a domain.
+
+        dom domain
+
+        returns vif indexes
+        """
+        return self.domain_devtype_ls(dom, 'vif')
 
-##     def domain_vif_ip_add(self, dom, vif, ip):
-##         dom = int(dom)
-##         return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
+    def domain_vif_get(self, dom, vif):
+        """Get a virtual network interface (vif) from a domain.
+
+        dom domain
+        vif vif index
+
+        returns vif device object (or None)
+        """
+        return self.domain_devtype_get(dom, 'vif', vif)
 
     def domain_vbd_ls(self, dom):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return []
-        devs = dominfo.get_devices('vbd')
-        return [ sxp.child_value(v, 'dev') for v in devs ]
+        """Get list of virtual block device (vbd) indexes for a domain.
+
+        dom domain
+
+        returns vbd indexes
+        """
+        return self.domain_devtype_ls(dom, 'vbd')
 
     def domain_vbd_get(self, dom, vbd):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        devs = dominfo.get_devices('vbd')
-        for v in devs:
-            if sxp.child_value(v, 'dev') == vbd:
-                return v
-        return None
+        """Get a virtual block device (vbd) from a domain.
+
+        dom domain
+        vbd vbd index
+
+        returns vbd device (or None)
+        """
+        return self.domain_devtype_get(dom, 'vbd', vbd)
 
     def domain_shadow_control(self, dom, op):
+        """Shadow page control.
+
+        dom domain
+        op  operation
+        """
         dom = int(dom)
         return xc.shadow_control(dom, op)
 
-    #============================================================================
 
 def instance():
+    """Singleton constructor. Use this instead of the class constructor.
+    """
     global inst
     try:
         inst
index a7e5aa3b2f2d441e260ba00b5715f322af240047..c43dcfe892b14d6cb8c764642ac26cb660270175 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/python
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 
 """Representation of a single domain.
@@ -16,7 +15,7 @@ import os
 
 from twisted.internet import defer
 
-import xen.ext.xc; xc = xen.ext.xc.new()
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
 import xen.util.ip
 
 import sxp
@@ -333,6 +332,9 @@ def _vm_configure2(val, vm):
 class XendDomainInfo:
     """Virtual machine object."""
 
+    STATE_OK = "ok"
+    STATE_TERMINATED = "terminated"
+
     def __init__(self):
         self.recreate = 0
         self.config = None
@@ -351,7 +353,7 @@ class XendDomainInfo:
         self.blkif_backend = 0
         self.netif_backend = 0
         #todo: state: running, suspended
-        self.state = 'running'
+        self.state = self.STATE_OK
         #todo: set to migrate info if migrating
         self.migrate = None
 
@@ -490,21 +492,42 @@ class XendDomainInfo:
         self.configs.append(val)
 
     def destroy(self):
-        if self.dom <= 0:
-            return 0
+        """Completely destroy the vm.
+        """
+        self.cleanup()
+        return self.destroy_domain()
+
+    def destroy_domain(self):
+        """Destroy the vm's domain.
+        The domain will not finally go away unless all vm
+        devices have been released.
+        """
+        if self.dom is None: return 0
         return xc.domain_destroy(dom=self.dom)
 
-    def died(self):
-        print 'died>', self.dom
+    def cleanup(self):
+        """Cleanup vm resources: release devices.
+        """
+        print 'cleanup>', self.dom
+        self.state = self.STATE_TERMINATED
         self.release_devices()
 
+    def is_terminated(self):
+        """Check if a domain has been terminated.
+        """
+        return self.state == self.STATE_TERMINATED
+
     def release_devices(self):
+        """Release all vm devices.
+        """
         print 'release_devices>', self.dom
         self.release_vifs()
         self.release_vbds()
         self.devices = {}
 
     def release_vifs(self):
+        """Release vm virtual network devices (vifs).
+        """
         print 'release_vifs>', self.dom
         if self.dom is None: return
         ctrl = xend.netif_get(self.dom)
@@ -512,6 +535,8 @@ class XendDomainInfo:
             ctrl.destroy()
 
     def release_vbds(self):
+        """Release vm virtual block devices (vbds).
+        """
         print 'release_vbds>', self.dom
         if self.dom is None: return
         ctrl = xend.blkif_get(self.dom)
index 7221785affd23fb90ad4cb59cd48272bd1783ca5..27ea8ef187236643b9d1efeb34a3ee46dd416699 100644 (file)
@@ -8,12 +8,12 @@
 """
 
 import os
-import xen.ext.xc
+import xen.lowlevel.xc
 
 class XendNode:
 
     def __init__(self):
-        self.xc = xen.ext.xc.new()
+        self.xc = xen.lowlevel.xc.new()
 
     def shutdown(self):
         return 0
index c8284dc485318cb836ddd770258f7dd1c1d40fb8..31ace1b84ea1af9045305f4cf3625108cfd89b44 100644 (file)
@@ -23,7 +23,7 @@ from twisted.internet import protocol
 from twisted.internet import abstract
 from twisted.internet import defer
 
-from xen.ext import xu
+from xen.lowlevel import xu
 
 from xen.xend import sxp
 from xen.xend import PrettyPrint
index be98a37fd5560c931e5b52ebba0da32b710890db..d68f84fa37623d6697cd537de3687dcf38188aad 100755 (executable)
@@ -1,5 +1,5 @@
-import xen.ext.xc; xc = xen.ext.xc.new()
-from xen.ext import xu
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
+from xen.lowlevel import xu
 from messages import msgTypeName
 
 VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
index ab8b22e41e5d322f870874f06726d1699db5cd5f..3227dc1b5e745c719f57ba204ead08460c54b5fd 100755 (executable)
@@ -3,7 +3,7 @@ from twisted.internet import reactor
 from twisted.internet import protocol
 from twisted.protocols import telnet
 
-from xen.ext import xu
+from xen.lowlevel import xu
 
 from xen.xend import EventServer
 eserver = EventServer.instance()
index e12d7b6e2427a153112b313f0a751ca5f4dd87e0..f3257ca8328db9afcbcab2b9fc5ba40b491927e3 100644 (file)
@@ -1,6 +1,6 @@
 import struct
 
-from xen.ext import xu
+from xen.lowlevel import xu
 
 DEBUG = 0